forked from EduCraft/curriculum-project-hub
192 lines
28 KiB
Markdown
192 lines
28 KiB
Markdown
# Accepted product-surface code inventory
|
|
|
|
Audit date: 2026-07-10
|
|
|
|
Scope: source-level inventory for the accepted SaaS product boundary in ADR-0020,
|
|
ADR-0021 and ADR-0022. This is not a claim that tests were executed during this
|
|
inventory. “Test evidence” below means a repository test exercises the named
|
|
path; “no direct test found” means a search of `hub/test/**/*.ts` found no request
|
|
to the named route or corresponding service call.
|
|
|
|
## Contract baseline
|
|
|
|
The destination is not a shared-bot, single-credential Hub. The repository's
|
|
current shared language says:
|
|
|
|
- an Organization owns its memberships, projects, teams, external connections
|
|
and settings (`CONTEXT.md:7-9`);
|
|
- a Platform Administrator creates and operates Organizations without becoming
|
|
their member, while an Organization Administrator is only an OWNER/ADMIN of
|
|
that Organization (`CONTEXT.md:11-17`);
|
|
- the Admin Surface is a private web control plane requiring the corresponding
|
|
authenticated administrator authority (`CONTEXT.md:19-21`);
|
|
- each Organization has its own Feishu application for login, bot messaging and
|
|
directory integration (`CONTEXT.md:23-25`);
|
|
- provider connections are Organization-scoped BYOK or an Organization-distinct
|
|
platform-managed connection (`CONTEXT.md:27-37`);
|
|
- capacity uses non-optional platform ceilings, optional lower Organization
|
|
limits, durable Organization-fair admission and audited emergency brakes
|
|
(`CONTEXT.md:39-77`).
|
|
|
|
ADR-0021 makes `/admin/platform` and `/admin/org/:orgSlug` separate guarded web
|
|
areas (`docs/adr/0021-org-admin-project-onboarding.md:23-40`), requires a
|
|
customer-owned Feishu app with encrypted Organization-scoped secrets
|
|
(`docs/adr/0021-org-admin-project-onboarding.md:42-47`), and pins both provider
|
|
credential modes as Organization-scoped (`docs/adr/0021-org-admin-project-onboarding.md:49-60`).
|
|
ADR-0022 makes its safety controls release requirements, not optional future UI
|
|
(`docs/adr/0022-layered-capacity-admission.md:22-77`).
|
|
|
|
Status vocabulary in this inventory:
|
|
|
|
- **HTTP-backed** / **Feishu-backed**: a production route/event handler is wired.
|
|
- **Service/test only**: code can be invoked directly, but there is no production
|
|
product entry point.
|
|
- **Partial**: part of the journey exists but the accepted end-to-end product
|
|
surface cannot complete it.
|
|
- **Missing**: no production entry and no suitable persistence/control model.
|
|
- **Contract divergence**: reachable behavior actively uses the wrong tenancy or
|
|
credential shape.
|
|
|
|
## Journey matrix
|
|
|
|
| Target journey | Reachable entry | Authorization | Persistence | Test evidence | Verdict and exact gap |
|
|
|---|---|---|---|---|---|
|
|
| Platform Administrator signs in | None. The admin plugin registers only Feishu auth and Organization routes (`hub/src/admin/plugin.ts:7-8`, `hub/src/admin/plugin.ts:31-46`). The only HTML is the Org Admin login page (`hub/src/admin/routes/authRoutes.ts:171-207`). | `PlatformRoleAssignment` and `PlatformRole.ADMIN` exist in the schema (`hub/prisma/schema.prisma:111-129`), but the HTTP guard explicitly says the platform control plane is not modeled (`hub/src/admin/auth/guards.ts:1-5`). | Role rows can be stored, but there is no platform session/identity binding, invite/bootstrap flow or platform-admin audit surface. | No platform-auth route test exists. | **Missing.** `/admin/platform` from ADR-0021 is not mounted, so no authenticated operator can reach any platform workflow. |
|
|
| Platform Administrator creates/lists/updates/operates Organizations | None. No `/api/platform/*` or Organization CRUD route is registered; the route composition is auth + `/api/org/:orgSlug/*` only (`hub/src/admin/plugin.ts:31-46`, `hub/src/admin/routes/orgRoutes.ts:24-103`). | No `requirePlatformAdmin` implementation; only `requireSession` and `requireOrgRole` exist (`hub/src/admin/auth/guards.ts:43-113`). | `Organization` has slug, name and ACTIVE/SUSPENDED/ARCHIVED status (`hub/prisma/schema.prisma:28-52`). | Organizations are created directly only by test setup, e.g. `prisma.organization.upsert` (`hub/test/integration/helpers.ts:60-77`) and a direct cross-org fixture create (`hub/test/integration/admin-explorer.test.ts:198-210`). | **Service/test only at the database layer.** Manual pilot onboarding has no safe production command, HTTP API or UI; status changes are also unreachable. |
|
|
| Platform Administrator configures an Organization's customer-owned Feishu app and checks readiness | None. Runtime accepts exactly one `feishuAppId`/`feishuAppSecret` pair in `AdminPluginConfig` (`hub/src/admin/plugin.ts:10-19`), and server startup reads one process-global app id, secret and bot open id (`hub/src/server.ts:47-52`). | No platform guard or Organization connection ownership check. | There is no Feishu application/secret model. `ExternalDirectoryConnection` stores provider/tenant/source metadata but no app id, bot id or secret reference (`hub/prisma/schema.prisma:196-214`). | No provisioning/readiness test exists. | **Missing + contract divergence.** There is no Organization-scoped encrypted Feishu connection or readiness workflow; production can operate only the one env-configured app. |
|
|
| Platform Administrator configures an Organization-distinct platform-managed provider key/base URL | None. No platform provider route or UI is registered. | No platform guard. | The accepted Lean type exists only in the semantic contract (`spec/Spec/System/Organization.lean:52-66`); Prisma has no provider-connection or provider-mode model (`hub/prisma/schema.prisma:26-214`). | Runtime tests prove env values are returned, not Organization values (`hub/test/unit/runtime-settings.test.ts:18-55`). | **Missing + contract divergence.** `EnvRuntimeSettings.provider` ignores its project scope and reads one process-global `ANTHROPIC_BASE_URL`/`ANTHROPIC_AUTH_TOKEN` (`hub/src/settings/runtime.ts:20-21`, `hub/src/settings/runtime.ts:46-67`). |
|
|
| Platform Administrator applies Organization/platform `DRAIN` or `STOP_NOW` and later resumes | None. | No platform guard, reason capture or scope check. | No workload-brake model exists; only the Lean contract defines `open`/`drain`/`stopNow` semantics (`spec/Spec/System/Capacity.lean:71-87`). | No workload-brake test exists. | **Missing.** The required audited, reason-bearing, reversible emergency control from ADR-0022 (`docs/adr/0022-layered-capacity-admission.md:69-72`) has no product or persistence surface. |
|
|
| Organization user logs in with that Organization's Feishu app | `GET /auth/feishu` and callback are HTTP-backed (`hub/src/admin/routes/authRoutes.ts:49-128`). The callback upserts a user and signs a cookie (`hub/src/admin/routes/authRoutes.ts:99-123`). | Login itself is public OAuth; Organization APIs later enforce session + active OWNER/ADMIN membership (`hub/src/admin/auth/guards.ts:43-113`). | `User.feishuOpenId` is one process-global unique identifier (`hub/prisma/schema.prisma:89-109`); the signed cookie carries user id/open id but no Organization or Feishu-connection identity (`hub/src/admin/auth/session.ts:18-23`). | Redirect and mocked callback are covered (`hub/test/integration/admin-auth.test.ts:164-230`); OAuth request construction/exchange is covered (`hub/test/unit/feishu-oauth.test.ts:8-81`). | **HTTP-backed but contract-divergent.** OAuth is built once from the process-global app credentials (`hub/src/admin/routes/authRoutes.ts:38-47`), and the implementation explicitly documents this deferral (`hub/src/admin/auth/feishuOAuth.ts:1-10`). There is no org-selecting login route, connection resolver or issuer/app identity in the user key. |
|
|
| Each Organization operates its own Feishu Bot | One WebSocket listener is production-wired (`hub/src/server.ts:76-90`). | Message actions are gated by project grants once a binding resolves (`hub/src/feishu/trigger.ts:715-755`), but there is no initial Organization/connection ownership gate for the inbound app. | Binding stores only `chatId -> projectId`, with no Feishu connection/application id (`hub/prisma/schema.prisma:287-304`). Event receipts store globally unique `eventId`, likewise without connection id (`hub/src/feishu/trigger.ts:687-707`). | Trigger, onboarding and event dedup are integration-tested (`hub/test/integration/trigger.test.ts:211-330`, `hub/test/integration/trigger.test.ts:878-928`). | **Feishu-backed for one bot, contract-divergent for SaaS.** Startup constructs one client and one WS client from one config (`hub/src/feishu/client.ts:854-901`). It cannot operate or route multiple Organization-owned apps. |
|
|
| Suspended/archived Organization is prevented from bot work | No platform status-change entry exists. Org HTTP APIs do reject non-ACTIVE Organizations (`hub/src/admin/auth/guards.ts:79-88`). | The Feishu trigger resolves an active chat binding directly and then project permissions; it does not load or check `Project.organization.status` (`hub/src/feishu/trigger.ts:715-755`). | Organization status exists (`hub/prisma/schema.prisma:30-52`). | No suspended-Organization trigger test exists. | **Partial and unsafe.** Even a database-side status change only blocks web admin; an already-bound chat remains triggerable through the bot path. |
|
|
| Logged-in Organization OWNER/ADMIN reaches the management panel | OAuth success redirects to `/admin/org/:slug` (`hub/src/admin/routes/authRoutes.ts:237-267`). | All Organization APIs default to OWNER/ADMIN through `requireOrgRole` (`hub/src/admin/auth/guards.ts:66-113`), and tests prove MEMBER is denied while ADMIN succeeds (`hub/test/integration/admin-auth.test.ts:95-131`). | Session is an HMAC cookie; user/membership is re-read for each guard (`hub/src/admin/auth/session.ts:31-57`, `hub/src/admin/auth/guards.ts:43-63`). | Guard behavior is integration-tested (`hub/test/integration/admin-auth.test.ts:56-131`). | **API-backed, UI missing.** The plugin says the static SPA is “later” (`hub/src/admin/plugin.ts:1-3`); no route/static handler serves `/admin/org/:slug`. OAuth therefore redirects to an unmounted page. |
|
|
| Organization OWNER/ADMIN manages members and roles | REST endpoints list/add/change/revoke members (`hub/src/admin/routes/membersRoutes.ts:20-98`). | OWNER/ADMIN route guard plus service rules: only OWNER may affect OWNER and the last OWNER cannot be removed (`hub/src/org/members.ts:1-8`, `hub/src/org/members.ts:97-205`). | `OrganizationMembership` persists org, user, role and revocation (`hub/prisma/schema.prisma:54-76`). | Add/list/last-OWNER protection is covered through HTTP (`hub/test/integration/admin-members-teams.test.ts:49-83`). | **HTTP-backed and persisted; management UI missing.** Addition requires a raw `feishuOpenId` and may create the `User` directly (`hub/src/org/members.ts:46-85`); there is no invite/accept or org-connection directory picker. Role-change/revoke variants have less direct HTTP coverage than add/list. |
|
|
| Organization OWNER/ADMIN manages teams and team membership | REST endpoints cover list/create/update/archive and membership add/revoke (`hub/src/admin/routes/teamsRoutes.ts:21-139`). | All routes require Organization OWNER/ADMIN; service verifies the team and added user belong to the same Organization (`hub/src/org/teams.ts:177-215`, `hub/src/org/teams.ts:263-275`). | `Team` and `TeamMembership` are Organization/project-principal persistence (`hub/prisma/schema.prisma:143-177`). | Create/add-member/archive is covered through HTTP (`hub/test/integration/admin-members-teams.test.ts:85-160`). | **HTTP-backed and persisted; management UI missing.** No production route exposes `ExternalDirectoryConnection`/external team binding sync, so the Feishu directory portion remains service-only. |
|
|
| Organization OWNER/ADMIN creates and manages Folders/Projects | REST endpoints cover explorer, folder create/update/archive, project create/detail/rename/move/archive (`hub/src/admin/routes/explorerRoutes.ts:33-212`). | All routes require Organization OWNER/ADMIN. Service operations scope folder/project ids to the Organization (`hub/src/org/explorer.ts:301-341`); HTTP cross-org lookup is tested. | Folder and Project carry `organizationId`; Folder is transparent and Project owns workspace/session/run relations (`hub/prisma/schema.prisma:238-285`). Project creation also creates a real workspace and default permission rows (`hub/src/projectOnboarding.ts:275-348`). | Create/list and move/archive are HTTP-tested (`hub/test/integration/admin-explorer.test.ts:66-196`); cross-org id access is tested (`hub/test/integration/admin-explorer.test.ts:198-223`). | **HTTP-backed and substantially tested; management UI missing.** This is the strongest accepted product slice. |
|
|
| Organization OWNER/ADMIN manages Feishu chat binding | HTTP can archive a binding (`hub/src/admin/routes/explorerRoutes.ts:214-227`). New binding is exposed through the Feishu onboarding card, not web. | Archive requires OWNER/ADMIN at HTTP and then project manager authorization in the shared service (`hub/src/projectOnboarding.ts:231-272`, `hub/src/org/explorer.ts:301-314`). Bind existing requires project MANAGE (`hub/src/projectOnboarding.ts:179-229`). | `ProjectGroupBinding` and the FEISHU_CHAT EDIT grant are transactionally stored (`hub/src/projectOnboarding.ts:190-215`, `hub/prisma/schema.prisma:287-304`). | Bind/one-active/archive/rebind is service-tested (`hub/test/integration/project-onboarding.test.ts:114-160`); card bind is integration-tested (`hub/test/integration/trigger.test.ts:271-330`). No direct HTTP archive test was found. | **Feishu + partial HTTP-backed; UI missing.** Binding identity is not scoped by Feishu application, so the 1:1 uniqueness and lookup are process-global rather than Organization-connection-scoped. |
|
|
| Organization OWNER/ADMIN manages project team access | REST list/grant/revoke endpoints exist (`hub/src/admin/routes/accessRoutes.ts:19-79`). | OWNER/ADMIN route guard; service refuses a team from another Organization (`hub/src/permissions/projectTeamAccess.ts:168-195`). | TEAM -> PROJECT `PermissionGrant` persists the role (`hub/prisma/schema.prisma:428-447`). | Grant/list/archive-induced revoke is HTTP-tested (`hub/test/integration/admin-members-teams.test.ts:123-156`). | **HTTP-backed and tested; UI missing.** Only team grants are surfaced. There is no HTTP management of direct USER/chat grants, `PermissionSettings`, or per-role `RoleTriggerGrant`. |
|
|
| Organization OWNER/ADMIN manages general project settings, roles/models and agent policies | Only `membersCanCreateProjects` is reachable through GET/PATCH `/settings` (`hub/src/admin/routes/orgRoutes.ts:46-81`). | OWNER/ADMIN route guard. | `OrganizationProjectSettings` stores only that Boolean (`hub/prisma/schema.prisma:78-87`). `PermissionSettings` exists, but no admin route references it (`hub/prisma/schema.prisma:449-467`). Model/role registry is explicitly an in-memory skeleton awaiting DB/admin wiring (`hub/src/agent/models.ts:65-79`). | The Boolean setting is HTTP-tested (`hub/test/integration/admin-auth.test.ts:133-162`); model env behavior is unit-tested (`hub/test/unit/runtime-settings.test.ts:4-64`). | **Partial.** The creation policy works, but the accepted “projects and configuration” control plane lacks editable permission settings, model/role settings and run policies. |
|
|
| Organization OWNER/ADMIN chooses BYOK vs platform-managed Provider mode; BYOK admin writes key/base URL | None. | No Organization provider guard because no route/service exists. | No Prisma provider connection, credential mode, encrypted secret handle or rotation metadata. The only persistent `provider` fields are descriptive strings on sessions/runs (`hub/prisma/schema.prisma:308-330`, `hub/prisma/schema.prisma:352-387`). | No provider-mode test. Existing tests assert the global env resolver (`hub/test/unit/runtime-settings.test.ts:18-55`). | **Missing + contract divergence.** Lean/ADR have the mode but production always calls `settings.provider("openrouter", { projectId })` (`hub/src/feishu/trigger.ts:195-199`), whose implementation discards the scope (`hub/src/settings/runtime.ts:46-67`). |
|
|
| Organization OWNER/ADMIN views sessions and runs | HTTP list and detail endpoints exist (`hub/src/admin/routes/sessionsRoutes.ts:14-45`). | OWNER/ADMIN route guard; service scopes project/session through Organization id (`hub/src/org/sessions.ts:6-23`, `hub/src/org/sessions.ts:49-87`). | `AgentSession`/`AgentRun` persist provider/model/status/tokens/cost and relations (`hub/prisma/schema.prisma:308-387`). | No direct test for these HTTP routes or `org/sessions.ts` was found. Trigger tests do prove sessions/runs are written, e.g. separate role sessions (`hub/test/integration/trigger.test.ts:850-876`). | **HTTP-backed and persisted, but untested at the product boundary and UI missing.** |
|
|
| Organization OWNER/ADMIN views Organization/Project/Folder usage | HTTP Organization and Project usage endpoints exist, with optional folder/date filtering (`hub/src/admin/routes/sessionsRoutes.ts:47-79`). | OWNER/ADMIN route guard. | Rollup derives Organization through Project and uses persisted token/cost facts (`hub/src/org/usage.ts:35-77`, `hub/src/org/usage.ts:106-151`). Missing cost increments `runsWithoutCost`, not known cost (`hub/src/org/usage.ts:106-118`). | No direct usage route/service test was found. `/cost` tests cover the Feishu session command, not these admin endpoints (`hub/test/integration/trigger.test.ts:423-480`). | **HTTP-backed and persisted, but incomplete relative to ADR-0022.** It does not attribute by Provider Connection because none exists, has no alert configuration/delivery, no UI, and no product-boundary tests. |
|
|
| Ordinary MEMBER creates a Project from an unbound Feishu group | Mentioning the bot in an unbound chat sends an onboarding card (`hub/src/feishu/trigger.ts:850-887`); card action calls shared project creation (`hub/src/feishu/trigger.ts:554-614`). | User must already exist and have an active Organization membership; ordinary creation is gated by `membersCanCreateProjects` (`hub/src/projectOnboarding.ts:149-177`, `hub/src/projectOnboarding.ts:380-403`). Creator receives USER MANAGE and the chat receives EDIT (`hub/src/projectOnboarding.ts:302-340`). | Project, Folder, workspace, binding, default settings and grants are persisted (`hub/src/projectOnboarding.ts:275-348`). | Card display/create/bind is integration-tested (`hub/test/integration/trigger.test.ts:211-330`); policy denial and grants are service-tested (`hub/test/integration/project-onboarding.test.ts:70-112`). | **Feishu-backed and well-tested for the single-app case.** For a user with multiple active memberships, onboarding refuses and says the org selector does not exist (`hub/src/feishu/trigger.ts:889-929`). With a per-Org app, the inbound connection should supply tenant context; current global bot cannot. |
|
|
| Ordinary MEMBER binds an existing manageable Project | Onboarding card lists unbound projects and card action binds one (`hub/src/feishu/trigger.ts:868-885`, `hub/src/feishu/trigger.ts:932-969`). | Non-admin candidate projects require `collaborator.manage`; bind service rechecks project MANAGE (`hub/src/feishu/trigger.ts:951-960`, `hub/src/projectOnboarding.ts:179-215`). | Binding + FEISHU_CHAT EDIT grant persist transactionally. | Card journey is integration-tested (`hub/test/integration/trigger.test.ts:271-330`). | **Feishu-backed for the single-app case; per-Organization connection routing is absent.** |
|
|
| Ordinary authorized member triggers an Agent Run from Feishu | Bound message event resolves Project, evaluates `agent.trigger`, resolves role/model/provider, creates session/run and starts the runner (`hub/src/feishu/trigger.ts:684-848`, especially `hub/src/feishu/trigger.ts:715-755` and `hub/src/feishu/trigger.ts:140-256`). | Missing sender id is fail-closed; project EDIT+ and optional role grant are enforced (`hub/src/feishu/trigger.ts:171-194`, `hub/src/feishu/trigger.ts:726-755`). | Session/run, messages, file changes, event receipt and audit fragments persist in Prisma (`hub/prisma/schema.prisma:306-405`, `hub/prisma/schema.prisma:496-525`). | Lifecycle, permission denial, dedup, audit, messages and interrupt have integration coverage (`hub/test/integration/trigger.test.ts:116-154`, `hub/test/integration/trigger.test.ts:597-607`, `hub/test/integration/trigger.test.ts:878-928`, `hub/test/integration/trigger.test.ts:983-1100`). | **Feishu-backed and tested for one process-global provider/Feishu connection.** It is not an Organization-resolved run: provider scope is ignored and bot/identity connection is absent. |
|
|
| Accepted work waits under Project/Organization/platform capacity and survives restart | Only a process-local queue per Project exists (`hub/src/feishu/triggerQueue.ts:18-45`). It is drained after the active Project run (`hub/src/feishu/trigger.ts:430-495`). | No Organization admission identity or capacity policy is evaluated. | Queue is a `Map` in memory (`hub/src/feishu/triggerQueue.ts:21-26`), not a Prisma model; accepted requests vanish on process exit. Expired entries are dropped and only logged (`hub/src/feishu/trigger.ts:475-483`). | FIFO/full/expiry behavior is unit-tested (`hub/test/unit/trigger-queue.test.ts:10-78`); locked-trigger enqueue/drain is integration-tested (`hub/test/integration/trigger.test.ts:609-673`). | **Contract divergence.** ADR-0022 requires durable bounded admission, Organization-fair scheduling, explicit EXPIRED/CANCELED states and notifications (`docs/adr/0022-layered-capacity-admission.md:33-46`); none are present. |
|
|
| Platform ceiling + optional lower Organization policy protect request/run/file/storage/entity capacity | None beyond Fastify defaults, a five-item Project queue and global max turns. `Fastify({ logger: true })` has no capacity options/plugins (`hub/src/server.ts:55-55`); dependencies include no rate-limit plugin (`hub/package.json:9-17`). | No admin policy route. | No capacity/limit model. `OrganizationProjectSettings` has only `membersCanCreateProjects` (`hub/prisma/schema.prisma:78-87`). Run policy contains only global `maxTurns` (`hub/src/settings/runtime.ts:24-37`, `hub/src/settings/runtime.ts:74-78`). The systemd unit has no CPU/memory/process controls (`hub/deploy/cph-hub.service:6-26`). | Unit tests cover only global max turns and the local queue (`hub/test/unit/runtime-settings.test.ts:58-64`, `hub/test/unit/trigger-queue.test.ts:5-113`). | **Missing.** None of ADR-0022's mandatory platform/org request rate, body, concurrency, file/archive, storage, entity-count, wall-time/tool/output or process limits are product-reachable or persistently enforced (`spec/Spec/System/Capacity.lean:13-60`). |
|
|
|
|
## Reachability summary
|
|
|
|
### Production-wired HTTP surface
|
|
|
|
The actual production plugin mounts these capability groups:
|
|
|
|
- global Feishu OAuth/session: `/auth/feishu`, callback, logout, `/api/me`, and
|
|
the minimal `/admin/login` HTML (`hub/src/admin/routes/authRoutes.ts:49-207`);
|
|
- Organization summary and one onboarding Boolean
|
|
(`hub/src/admin/routes/orgRoutes.ts:27-81`);
|
|
- Folder/Project explorer and binding archive
|
|
(`hub/src/admin/routes/explorerRoutes.ts:33-227`);
|
|
- member roles (`hub/src/admin/routes/membersRoutes.ts:20-98`);
|
|
- teams/team membership (`hub/src/admin/routes/teamsRoutes.ts:21-139`);
|
|
- TEAM -> PROJECT grants (`hub/src/admin/routes/accessRoutes.ts:19-79`);
|
|
- sessions and usage (`hub/src/admin/routes/sessionsRoutes.ts:14-79`).
|
|
|
|
Every `/api/org/:orgSlug/*` route uses the same OWNER/ADMIN guard. This satisfies
|
|
the clarified requirement that a management API cannot be used by an anonymous
|
|
or ordinary Organization member (`hub/src/admin/auth/guards.ts:43-113`). It does
|
|
not provide the accepted management **panel**: only `/admin/login` is rendered,
|
|
and the post-login `/admin/org/:slug` destination is not served.
|
|
|
|
### Production-wired Feishu surface
|
|
|
|
The trigger handler is a real end-to-end application path for one Feishu app:
|
|
event receipt/dedup, chat binding, permission checks, unbound-chat onboarding,
|
|
Project creation/binding, sessions/runs, streaming and interrupt. The service
|
|
wires the handler to a single SDK client and WebSocket listener
|
|
(`hub/src/server.ts:76-90`, `hub/src/feishu/client.ts:854-901`). The code and tests
|
|
therefore establish a useful single-app vertical slice, not the required
|
|
per-Organization connection architecture.
|
|
|
|
### Only database/service/test reachable
|
|
|
|
- Organization creation is direct Prisma fixture work
|
|
(`hub/test/integration/helpers.ts:60-77`).
|
|
- `PlatformRoleAssignment` is a stored type with no platform auth/HTTP surface
|
|
(`hub/prisma/schema.prisma:111-129`).
|
|
- external-directory sync has service code and can create membership rows
|
|
(`hub/src/permissions/externalSync.ts:40-90`), but no registered production
|
|
admin route.
|
|
- project `PermissionSettings` and `RoleTriggerGrant` are stored/enforced in
|
|
parts of the runtime, but have no Organization management API
|
|
(`hub/prisma/schema.prisma:449-494`).
|
|
|
|
### Entirely absent from runtime persistence/control plane
|
|
|
|
- Organization-scoped Feishu application connection and encrypted secret
|
|
handle;
|
|
- Organization-scoped Provider Connection, BYOK/platform-managed mode, encrypted
|
|
secret handle, rotation and runtime resolver;
|
|
- platform administrator session/guard, platform Organization CRUD, platform
|
|
admin invitation, platform-operation audit;
|
|
- versioned platform capacity ceiling loader/validation;
|
|
- Organization policy-limit rows and Organization admin endpoints;
|
|
- durable run request/admission state, fair Organization scheduler, queue cancel
|
|
and expiry notification;
|
|
- Organization/platform workload brake state and audited actions;
|
|
- usage/cost alert configuration and delivery;
|
|
- the Organization and platform management UI.
|
|
|
|
## Critical production blockers
|
|
|
|
1. **No Organization connection control plane.** The running service has one
|
|
Feishu app/bot and one provider token/base URL. This contradicts the defining
|
|
SaaS requirement even though Project/Team data is otherwise Organization-
|
|
scoped (`hub/src/server.ts:44-52`, `hub/src/settings/runtime.ts:46-67`).
|
|
|
|
2. **No platform control plane.** A Platform Administrator cannot authenticate,
|
|
create or operate an Organization, provision its Feishu app, configure its
|
|
platform-managed provider connection, or apply a workload brake. The only
|
|
apparent Organization creation path is direct database/test code.
|
|
|
|
3. **No usable management panel.** The backend Organization APIs are meaningful
|
|
and guarded, but OAuth redirects to an unmounted `/admin/org/:slug`; platform
|
|
UI does not exist at all (`hub/src/admin/plugin.ts:1-8`,
|
|
`hub/src/admin/routes/authRoutes.ts:237-267`).
|
|
|
|
4. **ADR-0022 is almost wholly unimplemented.** The in-memory Project queue is
|
|
specifically the implementation divergence ADR-0022 rejects; there are no
|
|
Organization-fair durable admission, mandatory layered limits, hard run/file/
|
|
storage/process budgets or emergency brakes
|
|
(`docs/adr/0022-layered-capacity-admission.md:79-88`).
|
|
|
|
5. **Tenant context is inferred too late and from global identifiers.** OAuth
|
|
creates a globally keyed `User`, bot events bind globally by `chatId`, and an
|
|
unbound-chat user with more than one Organization is rejected rather than
|
|
routed by the customer-owned Feishu connection (`hub/prisma/schema.prisma:89-109`,
|
|
`hub/src/feishu/trigger.ts:715-723`, `hub/src/feishu/trigger.ts:889-929`). This
|
|
blocks a correct multi-app implementation and also leaves Organization status
|
|
unenforced on the bot path.
|
|
|
|
## What is already worth retaining
|
|
|
|
The audit does not imply rewriting the working core. The following seams are
|
|
concrete and have useful test evidence:
|
|
|
|
- Organization ownership on Project/Team/Folder and same-Organization access
|
|
checks (`hub/prisma/schema.prisma:143-177`, `hub/prisma/schema.prisma:238-285`);
|
|
- OWNER/ADMIN guards and last-OWNER protection
|
|
(`hub/src/admin/auth/guards.ts:66-113`, `hub/src/org/members.ts:97-205`);
|
|
- reusable service operations for project creation, chat binding and grants
|
|
(`hub/src/projectOnboarding.ts:128-229`, `hub/src/projectOnboarding.ts:275-348`);
|
|
- Organization-scoped explorer/member/team/team-access HTTP APIs and their
|
|
integration tests;
|
|
- Feishu onboarding, project permission checks, session/run persistence and
|
|
dedup in the single-app vertical slice.
|
|
|
|
The shortest path to the accepted destination is therefore to add the missing
|
|
platform/connection/capacity control planes and real admin UI around these seams,
|
|
then change ingress and runtime resolution to carry an explicit Organization
|
|
connection identity end to end. Treating the existing env credentials as an
|
|
acceptable pilot fallback would preserve the wrong tenant boundary.
|