You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
plan(reach-edu-instance): rewritten on the identity spec's designed path — session tenancy, not sibling instances
Operator recheck was right: the id-didi-sh spec of record designs the
session to carry its workspace — minimal token (didi_id + sid), /api/me
org memberships, and augment-it explicitly specified to map org ↔
workspace per session. The running code built only the binary org gate
and papered the mapping over with the ACTIVE_CLIENT_ID instance pin;
worse, active client is instance-GLOBAL (workspace.activate switches
every connected session) and capability frames carry client untrusted.
v0.0.1.0 makes the designed mapping the plan: workspace org_id config,
per-session allowed_clients from /api/me (superuser = the operating-team
cross-client path), per-session activate with validation, and
server-side client enforcement on every dispatched frame — one domain
serving both tenants. The per-client-instance shape is demoted to a
named fallback if Stephenie's onboarding can't wait. Build order gains a
multi-tenant contamination proof script as step 1's acceptance.
Files changed:
- context-v/plans/Open-Augment-Didi-Sh-To-Reach-Edu.md
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RW28dw3kQAKXr2ZNefCukE
Copy file name to clipboardExpand all lines: context-v/plans/Open-Augment-Didi-Sh-To-Reach-Edu.md
+88-51Lines changed: 88 additions & 51 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,9 @@ authors:
7
7
- Michael Staton
8
8
augmented_with:
9
9
- Claude Code on Claude Fable 5
10
-
semantic_version: 0.0.0.1
10
+
semantic_version: 0.0.1.0
11
+
revisions:
12
+
- "2026-07-28 — v0.0.1.0 — REWRITTEN after rechecking the id-didi-sh spec of record (operator: 'the idea was it create an auth token that carried the workspace'). The spec confirms the intent: the token stays minimal (didi_id + sid) but /api/me supplies org memberships and augment-it is designed to map org ↔ workspace per session. The per-client-instance recommendation (v0.0.0.1's Option A) demoted to fallback; the designed org↔workspace session binding is now the plan."
11
13
tags:
12
14
- Plan
13
15
- Augment-It
@@ -32,39 +34,61 @@ single-tenant is the **door**: `DIDI_AUTH=required`,
32
34
`REQUIRED_ORG_ID=humain.vc`, `ACTIVE_CLIENT_ID=humain-vc` on
33
35
workspace-service.
34
36
35
-
## The load-bearing constraint
36
-
37
-
`ACTIVE_CLIENT_ID` pins the tenant PER-INSTANCE, not per-user-org.
38
-
Relaxing `REQUIRED_ORG_ID` alone would authenticate reach.edu users into
39
-
the humain-vc workspace. Safe multi-client therefore means either
40
-
per-client instances (each with its own pin) or real org→client session
41
-
binding (a feature in workspace-service). The house has a strong
42
-
precedent for the former: every client already gets its own Twenty, its
43
-
own hub, its own stack folder (`self-host-stack/client-stacks/<client>`).
44
-
45
-
## Recommended shape: a per-client instance (Option A)
46
-
47
-
`reach.augment.didi.sh` — a sibling instance in the same Railway project,
48
-
sharing the client-agnostic backends, pinning its own tenant:
|`workspace-service-reach`| NEW service from the same Dockerfile. Env: `DIDI_AUTH=required`, `REQUIRED_ORG_ID=reach.edu`, `ACTIVE_CLIENT_ID=reach-edu`, own tiny `/data` volume (sessions + clients root), `PORT=3001`|
54
-
|`shell-reach`| NEW build of the shell with its WS URL baked to `wss://ws.reach.augment.didi.sh/ws` (the WS URL is a build-time constant — see DEPLOYMENT.md gotchas) |
55
-
|`chat` / `strategy-curator` remotes | SHARED if the shell's remote registry allows cross-origin asset URLs per instance (they're static assets); else thin per-instance builds |
56
-
| DNS |`reach.augment` + `ws.reach.augment` CNAMEs per the custom-domain-cutover skill; both must stay on `*.didi.sh` for the shared `didi_session` cookie |
57
-
58
-
Why A over org-mapping: zero new auth code in the hot path, blast-radius
59
-
isolation (a reach-edu session cannot even express a humain-vc
60
-
workspace), per-client kill switch, and it matches the per-client stack
61
-
doctrine everywhere else.
62
-
63
-
**Option B (logged, not chosen): org→client binding in workspace-service**
64
-
— map didi org → allowed client(s) at session establishment, one domain
65
-
serves all tenants. Less infra, more auth surface; becomes worth it
66
-
around client #4 or when cross-client operators (us) want one login.
67
-
Revisit then.
37
+
## What the identity spec actually designed (recheck, 2026-07-28)
38
+
39
+
The id-didi-sh spec of record
40
+
(`ai-labs/context-v/specs/Id-Didi-Sh-Identity-Service.md`) is explicit:
41
+
42
+
- The **token stays minimal** — `didi_id` + `session_id` only
43
+
("Deliberately not in the token: orgs, roles, email").
44
+
-**`GET /api/me`** supplies org memberships + roles; and the augment-it
45
+
integration is specified as: *"per-capability authorization consults
46
+
cached `/api/me` org-roles **mapped onto workspaces**"* — with
47
+
per-service authorization state named directly: *"for augment-it:
48
+
**org ↔ workspace** per Workspaces-as-Tenant-Primitive."*
49
+
50
+
So the session is DESIGNED to carry its workspace(s), resolved through
51
+
org membership. What's running today implemented only the binary gate
52
+
(`REQUIRED_ORG_ID` membership yes/no) and papered over the mapping with
53
+
the `ACTIVE_CLIENT_ID` instance pin. Two gaps make the current state
0 commit comments