Operator can act as an org
Operator's ask (verbatim): "File a task so that Operator can act as an org."
Context (from advisor Task 6045): an operator cannot end a client's hosted machine. Nodes → Delete answers "This machine is hosted. Delete it from the Billing page." (apps/api/app/routes/nodes.py:3425). But billing endpoints resolve the caller's OWN tenant org and 404 on the operator plane (apps/api/app/routes/org_billing.py:369-375 `_tenant_org`; apps/api/app/routes/hostings.py, all `@org_admin(Tenancy.CALLER_PLANE)`). The sidebar's Orgs menu is only a read filter (apps/web/src/lib/orgScope.ts:1-15; apps/api/app/authz.py `_requested_org_filter`; apps/api/app/tenancy/seam.py:128-130), and the Billing link is hidden for operators (apps/web/src/components/Sidebar.tsx:368). So an operator has no console path to any org-admin-only surface (Billing, hostings, subscription, Jaah AI, etc.).
Requirements:
- An operator can explicitly enter "acting as <org>" from the console and leave it. While acting, every org-admin surface and endpoint serves that org exactly as it does for that org's Owner/Admin (Billing, hostings incl. Delete now / cancel / resume / change product, subscription, payment methods, settings).
- It is always visible: a persistent, unmissable indicator in the shell names the org being acted as, with a one-click exit. It cannot be confused with the Orgs read filter.
- Every write made while acting is audited with BOTH the operator's identity and the target org (who actually did it, on whose behalf).
- Scope never leaks: leaving act-as restores the operator plane; another tab or session is not silently switched; an org-admin endpoint never treats an operator as a tenant admin unless act-as is engaged.
- Reuse the existing authz/tenancy seam (Principal, Tenancy, `X-Jaah-Org-Scope` / `/api/auth/switch` precedent) rather than adding a parallel mechanism. Record the decision as an ADR entry.
- After this, the hosted-machine error on Nodes → Delete should give an operator a working route (e.g. act as the org → its hosting), not a dead end.
Out of scope: the Customers section epic (filed separately — it may build on this); changing what tenant org admins can do; impersonating a specific USER (this acts as the org's admin seat, not as a person).
Done means:
- An operator acts as a tenant org, opens its Billing, and runs Delete now on a hosting end to end on the dev stack, with a screenshot of the act-as indicator.
- The audit row for that delete names the operator and the org.
- API tests: an operator NOT acting as the org still gets 404 on `/api/org/billing/*` and `/api/rentals/*`; acting gets the org's data; acting as org A cannot read or change org B's hostings.
- `./dc check full` green.
Outcome
Operators act as a tenant org per tab, as its Owner seat. Writes are audited as operator + org; billing/hosting 404 unless acting. PR #5275 merged, Jaah Deploy green, ADR-0161. One e2e (access-requests) fails on develop itself. Follow-ups in report.
Artifacts
Activity
- Created
- Updated
- Run
- Runner started
- Awaiting response
- Awaiting response
- Awaiting response
- Awaiting response
- Awaiting response
- Runner resumed
- Runner ended (done)