From 574d6d9b0a3a9e86c805f9ecdfe189c8c1da14bd Mon Sep 17 00:00:00 2001 From: Hongming Wang Date: Tue, 14 Apr 2026 15:41:45 -0700 Subject: [PATCH] docs: sync documentation with 2026-04-14 tick-8 merge (#78) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CLAUDE.md: Go test count 740 → 746; MOLECULE_ORG_ID env var documented. - PLAN.md: new "Recently launched (2026-04-14 tick-8)" block covering Phase 32 PR #1 + paired private molecule-controlplane repo scaffolding. - docs/edit-history/2026-04-14.md: tick-8 breakdown. Co-Authored-By: Claude Opus 4.6 (1M context) --- CLAUDE.md | 2 +- PLAN.md | 3 +++ docs/edit-history/2026-04-14.md | 44 +++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index b92b221c..d9da6e2e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -216,7 +216,7 @@ OPENAI_API_KEY=... bash scripts/test-team-e2e.sh # E2E: Multi-template ### Unit Tests ```bash -cd platform && go test -race ./... # 740 Go tests (handlers, registry, provisioner, CLI, delegation, org, channels, wsauth — sqlmock + miniredis; +2 on 2026-04-14 tick-4 for TestSetGlobal_* / TestDeleteGlobal_* auto-restart branches (#64); +4 on 2026-04-14 tick-4 for TestRestartContext_* covering the synthetic restart-context A2A message (#65); +5 on 2026-04-14 tick-6 for TestPlugins_* covering the new UNION + `!`/`-` opt-out semantics in org.go mergePlugins (#71, resolves issue #68); +9 on 2026-04-14 tick-7 for TestCategoryRouting_* / TestAppendYAMLBlock_* (#75) + TestRuntimeSchedule_HasSourceRuntime / TestImport_OrgScheduleSQLShape / TestList_IncludesSourceColumn (#76); raw PASS-line count is higher due to table-driven subtests) +cd platform && go test -race ./... # 746 Go tests (handlers, registry, provisioner, CLI, delegation, org, channels, wsauth, middleware — sqlmock + miniredis; +6 on 2026-04-14 tick-8 for TestTenantGuard_* covering MOLECULE_ORG_ID passthrough/match/mismatch/missing/allowlist/exact-match (#78, Phase 32 PR #1); prior: +9 tick-7 for category_routing + schedules.source; +5 tick-6 for plugins UNION; +6 tick-4 for auto-restart + restart-context branches) cd canvas && npm test # 357 Vitest tests (store, components, hydration, buildTree, secrets API, org template import, ConfirmDialog singleButton + 7 native-dialog replacements) cd workspace-template && python -m pytest -v # 1140 pytest tests (adds platform_auth token store for Phase 30.1, memory_write activity logging) cd sdk/python && python -m pytest -v # 132 SDK tests (agentskills.io spec validator, CLI, AgentskillsAdaptor round-trip, workspace/org/channel validators, RemoteAgentClient Phase 30 flows) diff --git a/PLAN.md b/PLAN.md index 52b9d061..31644f6a 100644 --- a/PLAN.md +++ b/PLAN.md @@ -239,6 +239,9 @@ point for "what else is out there." - **GitHub issue #15** — Provisioner: auto-refresh `CLAUDE_CODE_OAUTH_TOKEN` from `global_secrets` on workspace restart → **DONE** via PR #64 (`SetGlobal` / `DeleteGlobal` now fan out `RestartByID` to every affected workspace). - **GitHub issue #19 Layer 1** — Platform-generated restart context → **DONE** via PR #65 (synthetic A2A `message/send` with `metadata.kind=restart_context`, `system:restart-context` caller prefix, 30s re-register wait). Layer 2 deferred to issue #66 (see Backlog item 15 above). +### Recently launched (2026-04-14 tick-8) +- **Phase 32 PR #1** — `TenantGuard` middleware (PR #78, merged `57a05686`). Public repo's only SaaS hook: when `MOLECULE_ORG_ID` env is set, non-allowlisted requests require matching `X-Molecule-Org-Id` header or 404. Unset → passthrough (self-hosted unchanged). Allowlist is exact-match: `/health` + `/metrics`. Paired with the private `Molecule-AI/molecule-controlplane` repo scaffolded this tick (Fly Machines provisioner stub, `/cp/orgs` CRUD, subdomain→fly-replay router, migrations 001-003 for `organizations`/`org_instances`/`org_members`). +6 `TestTenantGuard_*` tests. Phase 32 plan: follow-up PRs wire real Fly provisioner, WorkOS AuthKit, Stripe, Cloudflare, signup UX — all in the private repo except the single public middleware. + ### Recently launched (2026-04-14 tick-7) - **GitHub issue #24** — Runtime-added workspace_schedules drift on org re-import → **DONE** via PR #76 (new `source` column on `workspace_schedules` via migration `022`; org/import now upserts with `ON CONFLICT (workspace_id, name) DO UPDATE ... WHERE source='template'`, so runtime-added rows survive re-imports; legacy rows backfilled to `'template'`; +3 tests). - **GitHub issue #51** — PM hardcoded audit-category routing → **DONE** via PR #75 (generic `category_routing:` block in `org-templates//org.yaml` `defaults` + per-workspace override; rendered into each workspace's `config.yaml` via `renderCategoryRoutingYAML` using `yaml.Node` + `yaml.Marshal` for safe escaping; PM prompt replaced with generic config-lookup; +6 tests). diff --git a/docs/edit-history/2026-04-14.md b/docs/edit-history/2026-04-14.md index 32525732..19083b97 100644 --- a/docs/edit-history/2026-04-14.md +++ b/docs/edit-history/2026-04-14.md @@ -462,3 +462,47 @@ Merge commit `911580c6`. Routine docs sync for the prior tick. added; per-role plugin lists trimmed to deltas. - `org-templates/molecule-dev/pm/system-prompt.md` — hardcoded category table replaced with generic config-lookup instructions. + +## Summary — tick-8: TenantGuard middleware (Phase 32 foundation) + +One merge: PR #78 (TenantGuard). Phase 32 (Cloud SaaS launch) starts here. + +### PR #78 — `feat(platform): TenantGuard middleware — public repo's only SaaS hook` +Merge commit `57a05686`. Noteworthy: saas-foundation / auth-adjacent. + +- New `platform/internal/middleware/tenant_guard.go`: + - Reads `MOLECULE_ORG_ID` env at construction. If set → every non-allowlisted + request must carry matching `X-Molecule-Org-Id` or gets **404** (not 403, + to avoid leaking tenant existence to subdomain probers). If unset → + passthrough (self-hosted / dev / CI unchanged). + - Allowlist is exact-match (`/health`, `/metrics`) so Fly Machines health + probes + Prometheus scrape work without the header. + - `TenantGuardWithOrgID(id)` is the test constructor; ordinary callers use + `TenantGuard()`. +- Wired into `platform/internal/router/router.go` after `metrics.Middleware()` + so rejected requests still land on the 4xx counter. +- +6 tests: unset-passthrough, matching, mismatched-404-empty-body, missing-404, + allowlist-bypass, allowlist-is-exact-match. +- CLAUDE.md: test count 740 → 746; new `MOLECULE_ORG_ID` env var documented. + +### Paired work — private `molecule-controlplane` repo scaffolded +(Outside this monorepo; logged here because it anchors the open-core split.) + +- Initial commit `1bab493` on new private repo `Molecule-AI/molecule-controlplane`. +- Migrations 001 (organizations), 002 (org_instances), 003 (org_members). +- HTTP server: `/health`, `/cp/orgs` CRUD, subdomain + `X-Molecule-Org-Slug` + header fallback → `fly-replay: app=;instance=` header, + stamps `X-Molecule-Org-Id` so TenantGuard downstream accepts the request. +- `Provisioner` + `Lookup` interfaces; `Stub` in-memory impl (idempotent, + tested) + `Fly` stub returning `ErrNotImplemented` (real impl is Phase B). +- CI workflow: vet + build + test on push/PR. +- Follow-up PRs (in the private repo): real Fly Machines provisioner, WorkOS + AuthKit signup, Stripe billing, Cloudflare edge, signup UX, observability, + hardening. Full 9-phase plan documented in chat (phases A–I). + +### File deltas (public repo) +- `CLAUDE.md` — test count + `MOLECULE_ORG_ID` env var. +- `PLAN.md` — new "Recently launched (2026-04-14 tick-8)" block. +- `platform/internal/middleware/tenant_guard.go` — new. +- `platform/internal/middleware/tenant_guard_test.go` — new. +- `platform/internal/router/router.go` — wired middleware.