PRD: Pre-Onboarding E2E + Multi-Role Verification (Client Portal)
Status: Draft — Awaiting Approval
Version: 1.0
Author: Product Manager (upsquad-product-manager[bot])
Date: 2026-04-22
Repo: upsquad-ai/upsquad-core (cross-cuts upsquad-ai/upsquad-client)
Portal: client (app.upsquad.ai) — admin portal explicitly OUT of scope
Labels: prd, awaiting-approval, portal:client, qa-e2e
1. Purpose
UpsQuad's own pilot onboarding — where UpsQuad itself becomes the first real tenant — is imminent. Over the past four days, the platform has shipped Dashboard Data Integration (PRD #824), dev-bypass removal (client#110), mock-import CI gate (client#116), BYOA governance (core#827), agent lifecycle governance (core#826), Wave K.2.3 (core#917), and six UX bug fixes (client#117–#122). The platform is technically functional end-to-end, but it has never been exercised as a real user from sign-up through daily operation.
This PRD gates pilot cutover on behavioral verification: every persona, on every surface, doing the real flows, with the real data. It complements (it does not replace) the structural criticism in /tmp/ux-audit-client-portal.md.
1.1 Success Metrics
- Zero P0 bugs open at sign-off.
- ≤ 3 P1 bugs open, each with a documented, product-acceptable workaround.
- All personas (Owner / Director / Lead / Member / Agent) complete their canonical happy-path flows without hitting developer-surfaced artifacts (UUIDs, enum slugs, RPC names, TODO comments).
- All visibility boundaries verified — no persona sees data or controls above their clearance.
- All governance enforcement points verified — denied actions are actually denied, approved actions are actually executed, every action is audited.
- Top 15 flows captured as Playwright regression guards after the manual pass.
1.2 Non-Goals
- Admin portal verification (only ~5% built; admin#2 PRD is gated on this PRD passing).
- Paid/billing capture — PRD #552 (Pricing & Packaging) is explicitly out. Founder confirmation 2026-04-21: "paid MVP enabled after initial UpsQuad onboarding."
- Agent lifecycle upgrade flow (PRD #550) — in-scope for correctness of what exists, not of what is not yet shipped.
- Advanced UX polish, redesigns, or large IA restructures — tracked by the UX audit and by PRD #553 (Dashboard Intelligence) and #573 (Quad). This PRD does not block on those.
- Performance / load / stress testing — separate effort (see PRD #615 Sandbox Benchmark).
- Security penetration testing — separate effort.
- Accessibility full WCAG AA conformance — this PRD covers only basics (keyboard nav, labeled controls, no colour-only state).
2. Scope
2.1 In Scope
- Every
src/app/(portal)/**/page.tsxsurface inupsquad-client. - The sidebar and top-bar controls.
- Clerk sign-up → webhook → MemberService sync.
- Org creation and first-admin promotion.
- Agent deploy → LLM call → audit event.
- BYOA tool config, governance denial, budget cap enforcement.
- Approval request → approve → execute path, plus denial path.
- Session durability across page reload.
- Real-time badge and notification surfacing.
- Top-10 pages on a 375 px-wide viewport.
- Keyboard-only navigation on the top-5 pages.
2.2 Out of Scope
- Everything in §1.2 Non-Goals.
- Webhook endpoints exposed to third-party SCM platforms (separate PRD).
- Multi-tenant billing reconciliation (PRD #552).
- SCIM provisioning beyond smoke-test (PRD #549 / #550 scope).
3. Personas Matrix
Fixtures live in testdata/e2e/acme-corp.json (QA to create). Tenant is acme-corp-test — explicitly not upsquad-ai itself, so the real tenant onboarding starts clean.
3.1 Org Hierarchy (Fixture Tenant)
Acme Corp (tenant)
└── Engineering (pillar) ── Director: Dana ── Owner: Oscar
├── Platform Team ── Lead: Leo ── Members: Mia, Max
└── Product Team ── Lead: Lila ── Members: Mel, Mark
└── Operations (pillar) ── Director: Dina
├── Finance Team ── Lead: Lee ── Members: Meg, Matt
└── HR Team ── Lead: Lars ── Members: Min, Mo
└── Go-to-Market (pillar) ── Director: Drew
├── Marketing Team ── Lead: Lana ── Members: Moe, May
└── Sales Team ── Lead: Lyle ── Members: Mira, Miles
Plus three agents: copilot-engineering, copilot-finance, copilot-marketing, each deployed into its respective pillar's Platform / Finance / Marketing team.
3.2 Personas
| ID | Name | Clearance | Starting State | Must Succeed At | Must Be Denied |
|---|---|---|---|---|---|
fx-oscar-owner | Oscar | L5 Admin | First user, creates org | Full sign-up flow, org bootstrap, first admin promotion, create first team, deploy first agent, configure first guardrail, approve any request, view audit across org, manage API keys, access Billing + Settings | Nothing (ceiling persona) |
fx-dana-director | Dana | L4 Privileged | Invited by Oscar, accepts | Create sub-teams in Engineering pillar, approve Lead deploy requests, configure team-level tool budgets, view audit for Engineering pillar, manage roles within pillar | See / edit Operations or GTM; platform-wide guardrails; platform metrics; org-wide billing edits |
fx-leo-lead | Leo | L3 Sensitive | Invited by Dana, accepts | Deploy agent to Platform Team, set Platform Team budget cap, review approvals addressed to Platform Team, view audit for Platform Team, create API key for own scope | See / act on other teams; view org-wide budget; create another Lead; configure platform guardrails |
fx-mia-member | Mia | L1 Standard | Invited by Leo, accepts | Sign in, see own activity feed, chat with assigned copilot, see own submitted approvals, request an approval | Deploy or edit agents; change budgets; create keys; view other members' activity; view billing or admin sections |
fx-copilot-eng-agent | copilot-engineering | L3 (bot) | Deployed by Leo | Call whitelisted tools within Platform Team budget, submit approval requests, write to its own team's audit, respond in Quad chat | Call out-of-scope tools, exceed budget cap without approval, cross-team write, impersonate humans |
Canonical Clerk user IDs are assigned at fixture seeding time and recorded in testdata/e2e/acme-corp.json alongside the org ID, team IDs, and role assignments.
3.3 Acceptance Criteria (per persona)
Each persona gets a Persona Checklist — a markdown checklist file under tests/e2e/personas/<id>.md enumerating every surface × allowed-action and every surface × denied-action. QA completes the checklist per persona per surface. Sign-off is gated on 100% completion.
4. Function Inventory (by sidebar section)
Each row: Surface → Test Case → Expected State → Visibility Matrix. The matrix cells mean:
RW= persona sees and can editR= persona sees (read-only)—= persona does not see the control / page at allD= persona sees a "denied" or "insufficient clearance" state (with a friendly message, not a stack trace)
4.1 Workspace
| # | Surface | Test Case | Expected State | Oscar (L5) | Dana (L4) | Leo (L3) | Mia (L1) |
|---|---|---|---|---|---|---|---|
| W1 | /dashboard — KPI bar | Load page | All 4 KPI tiles render with real data from MemberService + analytics | RW | R (pillar-scoped) | R (team-scoped) | R (own activity only) |
| W2 | /dashboard — Activity feed | Paginate + filter | Only events visible to the persona's scope | RW full org | R pillar | R team | R own |
| W3 | /dashboard — Cost forecast widget | Load | 30-day forecast matches /billing/usage | RW | R | — | — |
| W4 | /dashboard — Alerts | Trigger a fake alert via fixture | Alert surfaces in badge + dashboard | RW | R relevant | R relevant | — |
| W5 | /dashboard — Workflows panel | List active workflows | Only in-scope workflows shown | RW | R pillar | R team | — |
| W6 | /quad | Send message "hello" | Response streams back, session persists across reload | RW | RW | RW | RW |
| W7 | /quad — Proactive conflict surfacing | Trigger a fixture conflict | Pinned proactive message appears in Quad | RW | RW (if in scope) | RW (if in scope) | — |
| W8 | /agents — list | Load | List shows only in-scope agents | RW all | R pillar | R team | R assigned |
| W9 | /agents/deploy | Walk deploy wizard for Platform Team | Wizard completes; agent appears in list; audit event recorded | RW | RW (pillar) | RW (team) | D |
| W10 | /agents/[agent_id] — detail | Load | Config, logs, metrics visible per scope | RW | R pillar | R team | R assigned |
| W11 | /agents/[agent_id] — chat | Send message | Response; transcript saved | RW | RW | RW | RW (assigned only) |
| W12 | /workflows | List and open | Only in-scope workflows | RW | R pillar | R team | — |
| W13 | /approvals — list | Load | Only requests in persona's approval scope | RW all | RW pillar | RW team | R (own submitted) |
| W14 | /approvals — approve | Approve a pending request | Request moves to approved; originating action executes; audit event | RW | RW (pillar) | RW (team) | D |
| W15 | /approvals — deny | Deny a pending request | Request denied; originating action rejected; audit event | RW | RW (pillar) | RW (team) | D |
| W16 | /approvals — diff view | Open diff for a config-change approval | Diff renders legibly (not raw JSON) | RW | RW | RW | D |
4.2 Governance
| # | Surface | Test Case | Expected | Oscar | Dana | Leo | Mia |
|---|---|---|---|---|---|---|---|
| G1 | /audit — list | Load + filter by persona, action, date | Events scoped; filters work | RW all | R pillar | R team | R own |
| G2 | /audit — export | Click export | CSV downloads; contents match current filter | RW | RW | RW | D |
| G3 | /keys — list | Load | Keys scoped | RW all | R pillar | R team (own) | — |
| G4 | /keys — create | Create a key scoped to Platform Team | Key created; secret shown once; audit event | RW | RW pillar | RW team | D |
| G5 | /keys — rotate | Rotate key | Old key invalidated; new shown once | RW | RW pillar | RW team | D |
4.3 Teams
| # | Surface | Test Case | Expected | Oscar | Dana | Leo | Mia |
|---|---|---|---|---|---|---|---|
| T1 | /teams — directory | Load | Teams scoped | RW | R pillar | R team | R assigned |
| T2 | /teams/[id] — detail, Tools tab | List configured tools | Only team-scoped tools | RW | RW pillar | RW team | R |
| T3 | /teams/[id] — Budget tab | Set monthly budget cap | Cap saved; audit event; over-budget tool calls now denied | RW | RW pillar | RW team | D |
| T4 | /teams/[id] — Members tab | Add / remove member | Member list updates; audit event | RW | RW pillar | RW team | D |
| T5 | /teams/structure — org chart | Load | Tree renders; persona's own node highlighted | RW | RW pillar | R team | R own |
4.4 Billing
| # | Surface | Test Case | Expected | Oscar | Dana | Leo | Mia |
|---|---|---|---|---|---|---|---|
| B1 | /billing — subscription overview | Load | Current plan + next invoice surface (display-only; paid MVP is out of scope) | RW | — | — | — |
| B2 | /billing/usage — usage summary | Load | Aggregate token / tool / agent-hour usage matches analytics | RW | — | — | — |
| B3 | /billing/usage — usage detail drilldown | Drill | Per-team, per-agent detail | RW | — | — | — |
| B4 | /billing/plans | Load | Plans listed; "upgrade" CTA is disabled or marked "coming soon" (paid MVP out of scope) | R | — | — | — |
| B5 | /billing/invoices | Load | Invoice list (likely empty for fixture) | R | — | — | — |
4.5 Settings
| # | Surface | Test Case | Expected | Oscar | Dana | Leo | Mia |
|---|---|---|---|---|---|---|---|
| S1 | /settings — profile | Edit own name | Saved; audit event | RW | RW | RW | RW |
| S2 | /settings — security | View sessions, sign out other devices | Current session preserved; others signed out | RW | RW | RW | RW |
| S3 | /settings/users | Invite user | Invitation email sent; pending user appears | RW | RW pillar | — | — |
| S4 | /settings/organization | Edit org name, logo | Saved; audit event | RW | D | D | D |
4.6 Admin (client-portal admin pages — distinct from admin portal)
These pages exist in client as power-user controls. Several are ComingSoon and are allowed to remain so for this PRD. For each, we verify at minimum that the "coming soon" state renders without errors, and that the route is not accidentally reachable by under-clearance personas.
| # | Surface | Test Case | Expected | Oscar | Dana | Leo | Mia |
|---|---|---|---|---|---|---|---|
| A1 | /admin/org | Load | Tree renders; edit controls work | RW | R pillar | — | — |
| A2 | /admin/users | Load; bulk role change | Works; audit event | RW | RW pillar | — | — |
| A3 | /admin/teams | Load | ComingSoon state or full page | R | — | — | — |
| A4 | /admin/approvals (policies) | Load | Approval policies list | RW | R | — | — |
| A5 | /admin/roles | Load | Role list; assign | RW | RW pillar | — | — |
| A6 | /admin/import | SCIM import fixture file | Import runs; results visible | RW | RW | — | — |
| A7 | /admin/guardrails | Load | Known P0 problem page (UX audit) — verify ONLY that (a) controls enforce correctly regardless of UX, (b) under-clearance users are denied. Do not block pilot on UX here; track UX in PRD #553 / UX audit backlog | RW | R | D | D |
| A8 | /admin/conflicts | Load | ComingSoon OK; no crash | R | — | — | — |
| A9 | /admin/metrics | Load | Platform metrics (may show demo data) | R | — | — | — |
5. Cross-Cutting Tests
These are not tied to a single page. Each carries a canonical ID used in bug reports.
| ID | Test | Success Criterion |
|---|---|---|
| C1 | Clerk sign-up end-to-end | New user completes Clerk flow → lands in portal → MemberService receives webhook → member row exists with correct email + clerk_user_id |
| C2 | Org creation + first-admin promotion | First signed-up user of a new org is promoted to L5; subsequent signups default to L1 |
| C3 | Clerk → MemberService webhook retry | Simulate webhook 500; retry succeeds; no duplicate member row |
| C4 | Clearance projection | Every page renders correctly for each persona; no undefined sections; no blank denials without message |
| C5 | BYOA tool config — happy path | Configure a tool; agent calls tool; call succeeds; audit event recorded; cost charged to team budget |
| C6 | BYOA — budget cap denial | With cap at $0.01, trigger a $0.10 tool call; call is denied at gateway; friendly error surfaces in agent chat; audit records the denial reason |
| C7 | Agent deploy → real LLM call | Deploy copilot-engineering → send a message → response streams from real LLM (not fixture) → audit event logs the call + tokens + cost |
| C8 | Governance — autonomy crossing | Configure autonomy level so "delete-file" needs approval; agent attempts delete-file; action pauses; approval request surfaces; on approve → executes; on deny → rejects; both paths audited |
| C9 | Approval chain — approve | Leo submits; Dana approves; originating action executes; no stuck state |
| C10 | Approval chain — deny | Leo submits; Dana denies; originating action rejected; Leo sees denial reason |
| C11 | Session durability — chat | Start a /quad conversation; reload page mid-stream; conversation resumes or is persisted and re-openable |
| C12 | Session durability — approval | Open an approval; reload mid-approve; approval state preserved; no double-execute |
| C13 | Real-time — badge count | Submit approval from Leo; Dana's portal badge increments within 10s without page reload |
| C14 | Real-time — Quad proactive | Trigger proactive conflict; pinned message appears in Quad within 10s |
| C15 | Accessibility — keyboard nav (top 5 pages) | Tab / Shift-Tab reaches every interactive control; Enter activates; visible focus ring; Escape closes modals |
| C16 | Accessibility — screen-reader labels (top 5 pages) | All form inputs have labels; all icon-only buttons have aria-label; landmarks (main, nav) present |
| C17 | Mobile (375 px) — top 10 pages | No horizontal scroll; no overlapping content; key CTAs reachable; sidebar collapses or drawer opens cleanly |
| C18 | Error recovery — network blip mid-deploy | Kill network for 3s during /agents/deploy step 3; user sees retry; completes on retry without duplicate agent |
| C19 | Error recovery — server 5xx during approval | Force 500 on approve-request; user sees friendly error; state unchanged; retry succeeds |
| C20 | Auth token expiry | Expire Clerk token mid-session; user is redirected to sign-in with return URL; on sign-in, lands back on original page |
| C21 | Dev artifacts absent | Grep every rendered page for user-facing strings matching UUID, action_type, org_unit, cascade, sticky-deny, TODO, RPC, *.edit, requires_approval; any hit = P1 bug |
6. Test Data / Fixtures
6.1 Tenant
- Name:
acme-corp-test - Not
upsquad-aiitself — keeps the real tenant clean for founder-run pilot onboarding on acceptance. - Clerk organization + subscription seeded via Clerk admin API using fixture script.
6.2 Members
3 pillars × 2 teams × 2–4 members, plus 3 directors and 1 owner = 17 human members + 3 agent members = 20 total.
Each has a fixed email of form <role>.<name>@acme-corp-test.upsquad.ai captured by Clerk sandbox.
6.3 Fixture File
- Location:
testdata/e2e/acme-corp.jsoninupsquad-client. - Fields per member:
id,clerk_user_id,email,name,clearance,pillar,team,role. - Seeded via
scripts/e2e-seed.shwhich calls Clerk + MemberService using fixture Clerk API key.
6.4 Agents
| Agent | Deployed To | Profile | Tools Whitelisted | Budget |
|---|---|---|---|---|
| copilot-engineering | Platform Team | software-engineer | git-read, github-issues-read, jira-read | $5 / mo |
| copilot-finance | Finance Team | financial-analyst | gsheet-read, gsheet-write, slack-post | $5 / mo |
| copilot-marketing | Marketing Team | content-writer | notion-read, notion-write, slack-post | $5 / mo |
7. Test Methodology
7.1 Phase 1 — Manual Pass (QA-led, 1 working day)
- QA agent drives a real browser as each persona in sequence.
- Follows persona checklist
tests/e2e/personas/<id>.md. - Any divergence from expected state → file bug per §8.
- Screenshots captured for P0 / P1 bugs using browser dev-tools.
7.2 Phase 2 — Fix Wave (1 working day)
- All P0 bugs fixed. ≤ 3 P1 with documented workaround accepted.
- P2 / P3 triaged into backlog with labels.
- Re-verification of just the fixed-bug paths, not full re-run.
7.3 Phase 3 — Automation (parallel, starting Phase 1)
- Playwright scripts for top 15 flows (all of §5 plus core persona happy paths from §4).
- Location:
tests/e2e/*.spec.tsinupsquad-client. - Runs in CI on every client-portal PR.
- A Playwright failure is a CI gate — blocks merge.
7.4 Tooling
- Browser: Chromium (primary), Firefox + WebKit smoke on C17 mobile tests.
- Recorder: Playwright
codegenfor initial capture, then hand-tuned. - Video: recorded on failure only (Playwright trace).
- Report:
playwright-report/HTML uploaded as CI artifact.
8. Bug-Filing Convention
8.1 Template
Title: bug(P<n>): <one-line symptom>
Example: bug(P1): Approvals page shows "action_type: tool_call" to non-technical user
Body (exact template):
**Found in:** PRD #950
**Persona:** <fx-id> (e.g., fx-dana-director)
**Surface:** <route or component> (e.g., /approvals)
**Severity:** P0 | P1 | P2 | P3
**Commit / SHA:** <client commit> / <core commit>
### Reproduction
1. …
2. …
### Expected
…
### Actual
…
### Screenshot / Video
<ref>
### Proposed Fix (optional)
…
8.2 Labels
Always: bug, qa-e2e, portal:client, one of P0 / P1 / P2 / P3.
Also one of: frontend, backend, or devops depending on root cause (QA's best guess; architect can re-label).
8.3 Auto-board-sync
All bugs pick up Status = Todo, Track = qa, Agent = qa-engineer on creation via scripts/board-sync.py. QA then re-triages Agent and Track as bugs are assigned.
9. Severity Rubric
| Severity | Definition | Examples |
|---|---|---|
| P0 | Blocks pilot onboarding. Data corruption, permission bypass, cannot complete a core flow, auth broken, agent runtime broken for any persona. | Mia can approve a request; agent deploy 500s every time; sign-up webhook drops payload |
| P1 | Pilot-degrading. Misleading state, developer-artifact leak, annoying UX a non-engineer would complain about, recoverable but visible. | Page shows a UUID field; "requires_approval" enum string surfaced; badge count wrong by 1 |
| P2 | Polish; acceptable for pilot with workaround. | Minor copy inconsistency; mobile padding off on a non-top-10 page; sluggish animation |
| P3 | Nice-to-have. | Help-text wording; tooltip delay; icon choice |
9.1 Pilot-Cutover Gate
Pilot cutover allowed when:
- 0 P0 open.
- ≤ 3 P1 open, each with a comment documenting the workaround and an acceptance note from PM.
- No limit on P2 / P3 but all must be triaged (labeled + assigned to owner).
10. Acceptance
10.1 QA Sign-off
QA comments on this PRD issue:
QA-E2E SIGN-OFF: All persona checklists complete. Bugs filed: <count> (<P0>P0 / <P1>P1 / <P2>P2 / <P3>P3). Open at cutover: <0> P0 / <≤3> P1. Passes §9.1 gate.
10.2 Architect Review
Principal Architect reviews for systemic concerns (not individual bugs):
- Are bugs clustered around a single subsystem (indicates deeper flaw)?
- Are any P1s actually re-classified P0s (permission or data issues)?
- Sign-off:
ARCH REVIEW: No systemic concerns. Cleared for product acceptance.
10.3 PM Acceptance
Product Manager verifies the delivered state against §1.1 Success Metrics and comments:
PM ACCEPTANCE: Pre-onboarding E2E verification complete. Ready for pilot cutover.
10.4 Founder Approval
Founder triggers the actual pilot cutover (re-seeding against upsquad-ai real tenant) after PM acceptance. This is explicitly a human-decision item per CLAUDE.md.
11. Delivery Timeline
| Day | Activity | Owner |
|---|---|---|
| D0 | PRD approved; fixture seed script ready | PM, QA |
| D1 | Manual pass Phase 1 (personas Owner + Director) | QA |
| D1–D2 | Bugs file as found | QA |
| D2 | Manual pass Phase 1 (personas Lead + Member + Agent) | QA |
| D2 | Playwright scripts for top 15 flows in draft | QA |
| D3 | Fix wave Phase 2 | SMEs (backend / frontend per bug label) |
| D3 | Re-verify fix-bug paths | QA |
| D3 | Playwright green in CI | QA + DevOps |
| D4 | Architect systemic review | Principal Architect |
| D4 | PM acceptance | PM |
| D4 | Founder cutover | Founder |
Aggressive target: pilot cutover by D+4 working days. If fix wave exceeds 1 day, timeline extends day-for-day.
12. Dependencies
- core#827 (BYOA governance) merged — verified D-2.
- core#826 (agent lifecycle governance) merged — verified D-2.
- core#917 (Wave K.2.3) merged — verified D-2.
- client#110 (dev-bypass removal) merged — verified D-2.
- client#116 (mock-import CI gate) merged — verified D-2.
- PRD #824 (Dashboard Data Integration) merged — verified D-2.
- Clerk sandbox with fixture-user creation API access.
- Real LLM API key for C7 (already in vault per memory
reference_api_keys_dev). - Fixture seed script
scripts/e2e-seed.sh(to be written). - Persona checklists
tests/e2e/personas/<id>.md(to be written).
13. Risks & Mitigations
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Bugs exceed 1-day fix wave | High | Delayed cutover | Triage ruthlessly; P2 / P3 never block; timeline extends day-for-day |
| P0 discovered at persona 4 of 5 | Medium | Re-run earlier personas | Fix, then targeted re-verify only affected surfaces |
| Fixture tenant leaks into production analytics | Low | Data pollution | Tenant name acme-corp-test; analytics queries exclude any tenant matching *-test |
| Real LLM cost blows up in testing | Low | Budget hit | Budget cap of $5/agent/mo enforced; testing in controlled windows |
UX audit's P0 on /admin/guardrails forces scope expansion | Medium | Scope creep | Explicitly deferred in A7: verify permissions + no-crash only, UX is separate PRD |
| Playwright flakiness blocks CI | Medium | Merge friction | Quarantine flaky tests after 2 failures; fix within 3 days or remove |
14. Open Questions
- Clerk fixture user creation — is there a rate limit on sandbox user creation that would block a 20-member fixture seed in one run? (QA to confirm D0.)
- Audit export CSV format — must it match a spec, or is best-effort OK? (PM default: best-effort, spec in a follow-up.)
- Mobile breakpoint — is 375 px correct (iPhone SE) or should we target 390 px (iPhone 12)? (Frontend SME to decide; either works for this PRD.)
- Playwright in CI — dedicated runner or shared? (DevOps to advise; either works.)
15. Changelog
| Version | Date | Changes |
|---|---|---|
| 1.0 | 2026-04-22 | Initial draft. 5 personas, 45 surface test cases, 21 cross-cutting tests, fixture tenant acme-corp-test, 4-day timeline. |