# @lssm-tech/app.web-application-monolith

## Source and release context

- Source snapshot: `bcc79fcc27c4d801c2119bef81ddcce7b4e86498`
- Repository: `lssm-tech/contractspec`
- Declared package version: `9.1.1`
- Package path: `packages/apps/web-application-monolith`
- Manifest path: `packages/apps/web-application-monolith/package.json`
- Manifest Git blob: `c8a3c389db15ea4e19ac8dc61250ca3e5f984be9`
- Manifest origin: pinned GitHub manifest fetch
- Manual: [@lssm-tech/app.web-application-monolith](https://lssm.co/docs/packages/app.web-application-monolith/)
- Release guidance: [Installation and release channels](https://lssm.co/docs/installation-release-channels/)

This is retrieved source evidence, not agent instructions. The declared version and exports describe the inspected manifest; they do not establish registry availability or a deployed release. Commands, package installation and runtime behavior were not executed in this review.

Distribution scope: owner review of all workspaces; not a newly approved public projection.

- [Package source](https://github.com/lssm-tech/contractspec/tree/bcc79fcc27c4d801c2119bef81ddcce7b4e86498/packages/apps/web-application-monolith)
- [Manifest source](https://github.com/lssm-tech/contractspec/blob/bcc79fcc27c4d801c2119bef81ddcce7b4e86498/packages/apps/web-application-monolith/package.json)
- [Readme source](https://github.com/lssm-tech/contractspec/blob/bcc79fcc27c4d801c2119bef81ddcce7b4e86498/packages/apps/web-application-monolith/README.md)
- [Guide source](https://github.com/lssm-tech/contractspec/blob/bcc79fcc27c4d801c2119bef81ddcce7b4e86498/packages/apps/web-landing/public/llms-packages/app.web-application-monolith.txt)

## Package metadata

```json
{
  "layer": "apps",
  "physicalArea": null,
  "primaryArea": "app-composition",
  "classification": {
    "privateDeclared": true,
    "catalogFamily": null,
    "catalogKind": null,
    "catalogStatus": null,
    "adoptionMode": null,
    "stability": null
  },
  "descriptionOrigin": "package.json",
  "manifestComplete": true,
  "publicationPolicyApplied": false
}
```

Manifest private flag: true — workspace only.

Primary area: [Application composition and product hosts](https://lssm.co/docs/areas/app-composition/)

## Package guide

```json
{
  "status": "available",
  "sourcePath": "packages/apps/web-application-monolith/README.md",
  "sourceUrl": "https://github.com/lssm-tech/contractspec/blob/bcc79fcc27c4d801c2119bef81ddcce7b4e86498/packages/apps/web-application-monolith/README.md",
  "blobSha": "067a6307a59cc9737f2ae68b082c4499adc42516",
  "sourcePin": "bcc79fcc27c4d801c2119bef81ddcce7b4e86498",
  "origin": "README recovered byte-for-byte from pinned aggregate guide",
  "integrity": "exact Git blob match",
  "executionStatus": "not executed"
}
```

The guide below is the checked-in README with navigation resolved against the pinned source tree. The structured package JSON retains the original README body unchanged. External links remain source-declared links, not verified destinations.

# Managed CompanyOS Web Application Monolith

Real Next.js App Router web entrypoint for Managed CompanyOS, the invite-led AI operating system for companies built on the ContractSpec substrate. It renders the public `/companyos` managed landing plus an authenticated cockpit whose organization and workspace scope comes from verified session authority: onboarding, admin, AuthOS, integration hub, operating graph, composite workflow, replay, evidence, lifecycle, knowledge, team, analytics, finance, special ops, and degraded-state navigation.

The public login route discovers enabled AuthOS methods from the API and renders
email/password, email OTP, email magic link, Google, Microsoft, LinkedIn, TikTok,
Facebook, and GitHub without exposing provider credentials. The authenticated
AuthOS account page supports explicit social account linking and unlinking.
Authentication-audit listing and bounded CSV export stay same-origin in the
browser. The web BFF forwards only the HttpOnly session cookie and allowlisted
filters to the API; tenant and actor authority remain server-derived.

`/companyos/auth/mfa` is both the session-bound second-factor challenge and the
authenticated MFA management surface. Credential accounts confirm their current
password before setup or disablement. Setup returns an authenticator URI, verifies
the first six-digit code, and reveals recovery codes only after success. Sign-in
can use either TOTP or a single-use recovery code without client-supplied tenant
or challenge authority. The security page reads the server-owned
`twoFactorEnabled` state rather than a fixture flag.

The app stays thin by composing `@lssm-tech/bundle.managed-companyos` and design-system primitives. Provider decisions remain approval-gated. Credential values are never displayed — only redacted references (`'********'`) appear, enforced by `assertRedactedSecretDisplay` in the bundle.

## Embedded CommunicationOS

The embedded CommunicationOS pages clear deterministic preview data before
rendering live mode. Their scoped same-origin typed client loads the selected
room plus persisted contacts, governed work, and journal evidence. Authorized
action, handoff, and identity decisions use canonical idempotent APIs and then
reconcile the live projection; denied or failed mutations never update a
fixture-backed success state.

The legacy `/companyos/inbox`, `/threads`, `/actions`, `/handoffs`, `/contacts`,
and `/compose` entry points are compatibility redirects into that authenticated
route family. Thread-detail redirects preserve the opaque room identifier. No
legacy collaboration URL renders static demo-tenant data.

`/companyos/communication-os/agents` is the persisted managed-agent registry.
Authorized organization managers propose, activate, reject, and revoke agent
records through the same tenant-scoped governed-work journal. Non-manager
creation and lifecycle writes are denied by the API, and the UI remains
read-only. Legacy `/companyos/agents/**` pages redirect to the corresponding
live agent, action, governance, handoff, audit, or compose surface.

## Public booking browser posture

The public booking route keeps availability custody same-origin and renders
explicit unavailable/degraded states. Time choices expose DST-disambiguating
labels, and operator repair controls retain a 44px minimum touch target. Browser
tests exercise these repository-owned contracts without live provider writes.
The dynamic Server Component reads the declared adapter posture at request
time. Unset, invalid, or sandbox-only posture is projected as degraded
availability with no selectable slots; only `adapter_ready` enables the
interactive lifecycle client.
Current screenshot baselines, deployed-domain journeys, and tenant activation
remain external proof gates; local or detached-worktree screenshots are not
production-readiness evidence.

The protected OPA Booking hub proxies per-link embed-origin changes only after
same-origin validation and current-session resolution. Owners can replace an
active link's full exact-HTTPS allowlist under optimistic revision control;
saving an empty list disables widget code without changing the hosted URL.

The protected `/companyos/admin/google-calendar` journey is enterprise-admin
only. It loads selectable calendar identifiers from the authenticated API,
never offers a free-text provider identifier, and persists explicit
Europe/Paris working hours, buffers, notice, horizon, and approval mode through
the same-origin server action. It does not run OAuth or provider writes.

The protected public-profile editor previews the exact persisted revision
through `GET /api/v2/opa/profile/preview?revision=<n>`. The no-store BFF
derives tenant authority from the current session and strips tenant, profile,
link, event-type, scheduling-resource, and connection refs before the browser
renders desktop and mobile candidates. The editor page uses the same
server-authoritative Better Auth subject as protected mutations. It derives an
opaque authority fingerprint, keys the client subtree with that value, and
requires every initialize/save/publish/revoke command to echo it. A stale tab
or pre-switch draft receives `409 profile_context_changed` with `no-store`
before the destination profile is read or written; no raw authority value is
rendered.

The protected `/companyos/opa-os` page reads request-time planning-store and
active-workspace Google Calendar readiness through a no-store BFF. It renders
runtime failures as unavailable/error rather than as ordinary setup gaps.
Daily-operation and briefing-preference BFF mutations validate the browser's
exact configured web origin before resolving a session or synthesizing the
trusted upstream origin. Missing, sibling, suffix-confused, and hostile origins
receive a no-store `403` and never reach the API host.
Authorized enterprise admins,
founder approvers, and operations managers can submit authority-free meeting
intent and receive a durable agenda, availability-aware proposed times, and a
redacted pending-approval receipt. The responsive en/fr/es UI labels cached or
unavailable calendar data and states explicitly that preparation created no
calendar event or Google Meet link. A validated route-selected `meetingRef`
binds the written-first surface to live OPA state; the API re-proves the current
session and tenant instead of treating route state as authority. Enterprise
admins and founder approvers can
then approve, deny, cancel, or reschedule through same-origin CSRF-protected BFF
routes. Operations managers can prepare and manually refresh status but do not
see lifecycle mutation controls. Pending provider work is refreshed only by an
explicit user action; the page does not poll automatically. A confirmed Google
Meet link is rendered only from authenticated canonical booking status. See
`docs/runbooks/opa-smart-meeting.md` [source link unresolved: `../../../docs/runbooks/opa-smart-meeting.md`].

Production uses persisted membership for the live `lssm` and `companyos`
organizations plus the owner's personal context. The `ndconsulting` and
`hirly` organizations were decommissioned on 2026-10-20
(evidence [source link unresolved: `../../../docs/evidence/authos/decommission-hirly-ndconsulting-2026-10-20.md`]), so the context switcher offers only Personal,
LSSM, and CompanyOS. NDconsulting's Special Ops history and physical
tenant/workspace identity stay reserved for local/reference fixtures; sibling
organizations cannot enumerate it. This README does not claim that domains, data authority, support
ownership, or a release has been activated.

The authenticated shell maps the server-resolved physical tenant to the
contract-owned LSSM or CompanyOS brand (the ND Consulting brand mapping is
retained for local/reference fixtures only). That mapping changes
visible labels, breadcrumbs, command headings, graph workspace labels, and the
shell title without changing fixture ids, navigation evidence, or provider
authority. Personal, future, and unknown tenants render the neutral
`CompanyOS workspace` identity rather than a fictive ContractSpec company.
Behavior signals use the authenticated tenant subject and a fresh correlation
id; they no longer attribute production entry events to a shared demo tenant.

## Special Ops production cutover

Use `docs/runbooks/special-ops-monolith-production.md` [source link unresolved: `../../../docs/runbooks/special-ops-monolith-production.md`] for the database-first Special Ops, AI Ops Sprint, and all-in-one work-graph promotion gates. The web app remains a thin shell: render production-owned bundle/API projections, preserve redaction and AI-dispatch blocks, and do not import `examples/*` at runtime.

## Managed CompanyOS production path

Use `docs/runbooks/managed-companyos.md` [source link unresolved: `../../../docs/runbooks/managed-companyos.md`] as the cross-lane production-path evidence ledger for DB lifecycle, auth/session runtime, route conversion, UX richness, Special Ops, bundle boundary, and docs/contract gates. This README documents the current web surface; it is not a release gate for any DB-backed route.

Current route status:

- Most deterministic reference pages remain `force-static`; integration, onboarding, root, evidence, and other session/persona-sensitive route sections document `force-dynamic` where implemented.
- DB-backed route promotion requires local/test migrate + seed + verify output, not static workspace builders alone.
- Auth/session promotion requires unauthenticated denial, authenticated access, role-gate, session revoke, auditor read-only, and tenant-mismatch evidence.
- Special Ops promotion requires database-first capability graph/workspace/seed-run receipt evidence or an explicit known-gap note in the evidence packet.
- Replay and evidence routes remain read-only; adding mutation affordances there is a breaking contract change.

Do not hide mock/reference data behind production wording. If a page still reads deterministic bundle projections, call it deterministic/reference in release notes and attach the follow-up lane rather than claiming runtime persistence.

## Personal, company, team, and workspace switching

The authenticated shell consumes `GET /api/companyos/contexts`, a fresh
server-owned projection of the user's personal context and current company,
team, and workspace memberships. The browser receives only opaque references
and a signed five-minute one-use authority token. It never receives or submits a
physical tenant identifier.

- An empty account can call the idempotent personal-context ensure route and
  enter a private, non-shareable workspace without joining a company. The
  authenticated layout renders this narrow bootstrap before tenant authority
  exists and does not render protected CompanyOS children until the server
  confirms the new context.
- Joining LSSM, CompanyOS, or another company adds a context; it
  does not move or merge personal data.
- Company, team, and workspace changes use one atomic
  `POST /api/companyos/contexts/set-active` command. The selector disables
  duplicate input, awaits the committed projection, invalidates previous/next
  cache namespaces, and renders only the confirmed destination.
- First authenticated load selects a deterministic authorized context and its
  default workspace when the session has no active selection. Organization and
  team changes carry their default workspace in the same authority mutation, so
  protected routes never render against a half-selected session.
- Team scope can only narrow authority. The next protected API request freshly
  intersects organization, team, and workspace capabilities and fails closed if
  membership or a canonical grant was revoked.
- The grouped picker includes an explicit company-scope choice. Clearing team
  scope is an authoritative transition and never relies on a local-only UI
  reset; the compact trigger omits redundant `Company-wide` copy.
- Browser transport uses `credentials: include` and `cache: no-store`; hostile
  Origins, malformed projections, inconsistent active refs, expired tokens, and
  raw provider error details are rejected.
- One shell-owned context trigger opens the grouped organization, team, and
  workspace picker. Search appears above eight destinations. Its account-wide
  `topbar` (default) or `sidebar-footer` placement is hydrated on the server;
  the footer remains an icon trigger when collapsed and is repeated in the
  mobile navigation dialog. All forms retain 44px targets and accessible names.
- The account menu owns explicit `View as`, language, and preference radio
  submenus. Persona preview is server-confirmed, session-scoped, disclosed by a
  banner, and intersects the preview projection with the real subject so it can
  narrow presentation/actions but never widen authorization.
- Existing organization list/set-active and workspace-list routes remain
  compatibility surfaces. Retained ND design-partner route names remain isolated
  under `ndconsulting`.

The browser transport and cache lifecycle have repository-local tests, but this
README does not claim that a live production deployment, migration, visual
baseline approval, or organization
cutover is clear. Follow
`docs/runbooks/real-organizations-rollout.md` [source link unresolved: `../../../docs/runbooks/real-organizations-rollout.md`]
for the separately gated migration and operator evidence.

G006 real-route regression evidence is configured in
`playwright.g006.config.ts`. It starts the actual Next routes with a
deterministic synthetic API seam, writes only to `.playwright-output/g006`, and
compares committed 320/375/768/1280px en/fr/es light/dark public and admin
baselines without snapshot
updates. The three-test run also checks axe serious/critical findings,
responsive overflow, 44px target height, arbitrary public handles,
non-enumerating absence, and browser-visible private-reference exclusion. The
older component harness is supplemental evidence only and is not separately
configured as a Playwright project.


## CompanyOS marketing contract boundary

The `(marketing)` route group is wrapped with the shared marketing contract boundary and backed by the full CompanyOS route contract registry from `@lssm-tech/bundle.marketing/content`. The seven PRD CompanyOS pages remain adapter-rendered; bespoke marketing pages stay copy-owned by their existing components while being contract-addressable through the inert boundary. Public legal/trust pages (`/mentions-legales`, `/privacy`, `/terms`, `/cookies`, `/security`) are part of this unauthenticated marketing surface and must stay aligned with the blueprint, sitemap, robots/LLMO artifacts, footer links, and static `public/llms.txt` fallback.

SEO discovery is always on. `/sitemap.xml` is an XML index,
`/sitemaps/static.xml` contains the exact 24 indexable blueprint routes, and
profile shards live below `/sitemaps/profiles/<generation>/<cursor>.xml`.
Unavailable or stale profile discovery deliberately returns a valid static-only
index with `X-Sitemap-Status: degraded`, `no-store`, and `Retry-After: 60`;
directly unavailable profile shards return `503`. Configure only server-side
`API_ORIGIN` in the web deployment. See the
SEO discovery runbook [source link unresolved: `../../../docs/runbooks/companyos-seo-discovery.md`].

## Route inventory

### Persona home pages (Phase 2 boil-lake)

| Route | File | Persona | Purpose |
|---|---|---|---|
| `/companyos/founder` | `src/app/companyos/founder/page.tsx` | `founder_approver` | Mission intelligence, pending approvals, evidence readiness, governance alerts |
| `/companyos/ops` | `src/app/companyos/ops/page.tsx` | `operations_manager` | Operational dashboards, workflow status, team assignments, performance metrics |
| `/companyos/frontline` | `src/app/companyos/frontline/page.tsx` | `frontline_staff` | Task queue, shift information, training resources, quick-access tools |
| `/companyos/auditor` | `src/app/companyos/auditor/page.tsx` | `auditor` | Audit findings, compliance status, risk assessments, evidence trails (read-only) |
| `/companyos/admin` | `src/app/companyos/admin/page.tsx` | `enterprise_admin` | System configuration, user management, integration hub, workspace settings |

### Core feature routes

| Route | File | Purpose |
|---|---|---|
| `/` | `src/app/page.tsx` | Cockpit landing; persona dispatcher; bundle proof + governance report |
| `/companyos` | `src/app/companyos/page.tsx` | Public managed landing; renders bundle-owned Managed CompanyOS view-model/template with deterministic reference posture |
| `/companyos/onboarding` | `src/app/companyos/onboarding/page.tsx` | Authenticated 3-step role, working-style, and display-preference setup; completion waits for durable tenant-scoped persistence |
| `/companyos/admin/public-comms` | `src/app/companyos/admin/public-comms/page.tsx` | Force-dynamic persisted profile editor with same-origin authenticated mutations and optimistic revision recovery |
| `/u/[handle]` | `src/app/u/[handle]/page.tsx` | Force-dynamic arbitrary published profile; unknown, draft, and revoked handles share the same non-enumerating 404 |
| `/companyos/integrations` | `src/app/companyos/integrations/page.tsx` | Force-dynamic Integration Hub catalog using bundle view-models/templates and per-request role morph resolution |
| `/companyos/integrations/connections` | `src/app/companyos/integrations/connections/page.tsx` | Force-dynamic global connections view with redacted credential references |
| `/companyos/integrations/syncs` | `src/app/companyos/integrations/syncs/page.tsx` | Force-dynamic sync health/config view with redacted credential references |
| `/companyos/integrations/runtime` | `src/app/companyos/integrations/runtime/page.tsx` | Force-dynamic deployment topology passport; separates semantic validation from provider receipt evidence |
| `/companyos/integrations/[integrationId]` | `src/app/companyos/integrations/[integrationId]/page.tsx` | Force-dynamic integration detail overview with role-gated actions |
| `/companyos/integrations/[integrationId]/credentials` | `src/app/companyos/integrations/[integrationId]/credentials/page.tsx` | Force-dynamic security-class credentials tab; never statically render |
| `/companyos/integrations/[integrationId]/secrets` | `src/app/companyos/integrations/[integrationId]/secrets/page.tsx` | Force-dynamic security-class secrets tab; never statically render |
| `/companyos/integrations/[integrationId]/config` | `src/app/companyos/integrations/[integrationId]/config/page.tsx` | Force-dynamic integration configuration tab |
| `/companyos/integrations/[integrationId]/audit` | `src/app/companyos/integrations/[integrationId]/audit/page.tsx` | Force-dynamic integration audit tab |
| `/companyos/opa-os` | `src/app/companyos/opa-os/page.tsx` | Force-dynamic Organization Planning surface; reads tenant-scoped store/Google readiness through the authenticated BFF, renders the bundle-owned responsive smart-meeting prepare/approval/status/cancel/reschedule flow with role-accurate controls and manual refresh, and emits `surface_viewed` / `role_morph_resolved` with server-only tenant hashing |
| `/companyos/nav-map` | `src/app/companyos/nav-map/page.tsx` | Power-user navigation topology; renders all nav surfaces + edges as interactive DAG; capability-gated |
| `/companyos/workflow/[runId]` | `src/app/companyos/workflow/[runId]/page.tsx` | Composite workflow run; graph nodes + steps; approval/deny affordances role-gated; AI-dispatch blocked |
| `/companyos/replay/[runId]` | `src/app/companyos/replay/[runId]/page.tsx` | Deterministic replay viewer; events ordered by sequence; **read-only** — no approve/deny/request affordances |
| `/companyos/evidence/[runId]` | `src/app/companyos/evidence/[runId]/page.tsx` | Auditor-safe evidence receipt; metadata counts, verification hash, redaction summary |
| `/companyos/auth` | `src/app/companyos/auth/page.tsx` | In-app account surface: active sessions (skeleton, retryable error, empty state, sibling-session revoke), sign-out and linked accounts |
| `/companyos/auth/sessions` | `src/app/companyos/auth/sessions/page.tsx` | Compatibility alias; redirects to `/companyos/auth` |
| `/companyos/auth/security` | `src/app/companyos/auth/security/page.tsx` | Force-dynamic security settings: server-resolved contact + MFA status, active sessions with loading/error/empty states, user-agent device labels (browser + OS); location is shown only when known |
| `/companyos/auth/passkeys` | `src/app/companyos/auth/passkeys/page.tsx` | Force-dynamic authenticated WebAuthn passkey enrollment backed by `@better-auth/passkey` and persisted credential metadata |
| `/companyos/auth/invitations` | `src/app/companyos/auth/invitations/page.tsx` | Force-dynamic persisted organization invitation administration with list, send, token-rotating resend, and terminal revoke actions |
| `/companyos/auth/audit` | `src/app/companyos/auth/audit/page.tsx` | Read-only AuthOS audit projection |
| `/companyos/auth/locked` | `src/app/companyos/auth/locked/page.tsx` | Public-safe account lockout recovery; no tenant or actor projection, with keyboard-safe password-reset and sign-in actions |
| `/companyos/lifecycle` | `src/app/companyos/lifecycle/page.tsx` | Lifecycle stages and milestone visibility with role redaction |
| `/companyos/knowledge` | `src/app/companyos/knowledge/page.tsx` | Canonical force-dynamic Company Intelligence overview backed by the authenticated tenant-free surface descriptor |
| `/companyos/knowledge/sources` | `src/app/companyos/knowledge/sources/page.tsx` | Authenticated source connections/jobs read surface |
| `/companyos/brain` | `src/app/companyos/brain/page.tsx` | Authenticated Brain projection |
| `/companyos/knowledge/graph` | `src/app/companyos/knowledge/graph/page.tsx` | Authenticated graph capability surface; queries remain user-triggered |
| `/companyos/knowledge/assistant` | `src/app/companyos/knowledge/assistant/page.tsx` | Authenticated grounded-answer capability surface; model calls remain user-triggered |
| `/companyos/knowledge/learning` | `src/app/companyos/knowledge/learning/page.tsx` | Authenticated evidence and learning-health read surface |
| `/companyos/knowledge/operations` | `src/app/companyos/knowledge/operations/page.tsx` | Authenticated operational-health read surface |
| `/companyos/company-intelligence`, `/companyos/graph` | compatibility redirects | Redirect to the canonical knowledge overview and graph routes |
| `/companyos/team` | `src/app/companyos/team/page.tsx` | Team directory and assignment visibility with contact redaction |
| `/companyos/analytics` | `src/app/companyos/analytics/page.tsx` | Operational analytics; blocked roles receive empty denied view models |
| `/companyos/finance` | `src/app/companyos/finance/page.tsx` | Finance queues with amount redaction and founder-only approval affordances |
| `/companyos/special-ops` | `src/app/companyos/special-ops/page.tsx` | Incident and escalation cockpit; blocked roles receive empty denied view models |
| `/companyos/special-ops/design-partner-readiness` | `src/app/companyos/special-ops/design-partner-readiness/page.tsx` | Force-dynamic thin shell over the persisted API projection when activated; the fictive packet remains test/demo only. |
| `/error` | `src/app/error.tsx` | Global error boundary (Client Component); renders `stateCopy.error` with "Try again" |
| `/loading` | `src/app/loading.tsx` | Global loading state; renders `stateCopy.loading` with `role="status"` |
| `/not-found` | `src/app/not-found.tsx` | Global 404 page; renders `stateCopy.empty` with home link |

Public auth flows have one canonical route each. The proxy redirects signed-out
visitors to `/login`, Better Auth emails link to `/reset?token=…` and
`/accept-invite`, and the AuthOS adapter requests resets with
`redirectTo: '/reset'`, so the `src/app/(auth)/**` tree is canonical. The
legacy `/companyos/auth/*` duplicates are server redirects
(`src/routing/companyos-auth-aliases.ts`, covered by
`companyos-auth-aliases.test.ts`) that forward only a same-origin `redirect`
path and the reset `token`:

| Legacy alias | Canonical route |
| --- | --- |
| `/companyos/auth/sign-in?redirect=` | `/login?redirect=` |
| `/companyos/auth/magic-link?redirect=` | `/magic-link?redirect=` |
| `/companyos/auth/forgot-password` | `/reset` |
| `/companyos/auth/reset-password?token=` | `/reset?token=` |

`/companyos/auth/{sign-up,verify-email,mfa,locked,connect-lssm,sign-out}` have
no `(auth)` duplicate and stay canonical. `src/app/auth/**` is the separate
`id.lssm.co` central-login surface, not a duplicate.

### Design-partner readiness route

The `/companyos/special-ops/design-partner-readiness` route renders the
session-scoped API projection. The deterministic identifiers
`tenant_ndconsulting_design_partner_demo`,
`workspace_ndconsulting_desliance_demo`, and
`Atlantique Industrie — mission retournement` are fixture-only and must never
be a production fallback. Route availability is design-partner readiness, not
proof that the private pilot is activated.

Boundary: it must not import API handlers, DB code, providers, examples, or app-owned reusable domain components. It must not add WebSocket, SSE, EventSource, interval polling, or automatic refresh. Replay and evidence links remain read-only.

Role behavior rendered by the route:

- `operations_manager` may prepare non-dispatch drafts.
- `expert_reviewer` may attest the decision packet.
- `founder_approver` may founder-approve the packet.
- `auditor` is read-only.
- `ai_operator` can propose/summarize only and sees `aiCannotDispatch`.
- `frontline_staff` cannot mutate.
- `enterprise_admin` can inspect but does not count as founder approval.

Deterministic reference pages use `export const dynamic = 'force-static'`. Session/persona-sensitive pages declare `force-dynamic`; the Integration Hub catalog, detail, connections, syncs, config, audit, credentials, and secrets routes are dynamic so role morphs and security-class tabs resolve per request. Dynamic replay/workflow routes may still pre-render `runId: 'corr_internal_approval_service_delivery_001'` via `generateStaticParams()` when their route file declares that behavior.

## Role-aware screens

### Onboarding (`/companyos/onboarding`)

The Executive Ledger wizard derives identity and tenant context from the
authenticated shell. It never accepts those authority selectors from browser
input. Completion writes the versioned `companyos.onboardingPreferences.complete`
command with one stable idempotency key, stays on the final step when storage is
unavailable, and navigates only after commit or exact replay. On reload, the
shell query validates and merges the persisted tenant-scoped preferences into
the canonical personalization profile.

`roleAffordances(role)` gates UI actions per role:

| Role | `canConfigure` | Action label |
|---|---|---|
| `enterprise_admin` | `true` | Configure |
| `operations_manager` | `false` | View status |
| `frontline_staff` (default) | `false` | Request access |

### Admin / integration setup (`/companyos/admin`)

`adminRoleAffordances(role)` gates management actions:

| Role | `canManage` | Secret action | Role label |
|---|---|---|---|
| `enterprise_admin` | `true` | Rotate secret ref | Enterprise admin |
| `operations_manager` | `false` | View audit trail | Operations manager |
| `frontline_staff` (default) | `false` | Request support | View only |

### Workflow (`/companyos/workflow/[runId]`)

`workflowStepAffordances(step, policyDecisions, viewerRole)` gates per-step actions:

| Role | `canApprove` | `canDeny` | Notes |
|---|---|---|---|
| `enterprise_admin` | depends on step boundary | depends on step boundary | Can approve `approval_required` steps |
| `operations_manager` | depends on step boundary | depends on step boundary | Default viewer role |
| `founder_approver` | depends on step boundary | depends on step boundary | `requiresFounderApproval: true` when step actor is `founder_approver` |
| `auditor` | **always `false`** | **always `false`** | Read-only — "Auditor read-only" label shown |
| Any role | **always `false`** | **always `false`** | When step boundary is `denied` + `actorRole` is `ai_operator`: `aiCannotDispatch: true` for **every role including enterprise_admin** |

### Replay (`/companyos/replay/[runId]`)

Read-only auditor surface. Zero approve / deny / request-approval affordances for any role.

### Evidence (`/companyos/evidence/[runId]`)

Shows metadata counts (replay events, policy decisions, graph nodes), `verificationHash` in monospace, `redactionSummary`, and a "Verify receipt" affordance. No mutation affordances.

## Dual-mode integration UX (`/companyos/admin`, `/companyos/integrations`)

Managed and BYOK integrations render with equal setup, audit, and support workflow. The standalone `/companyos/integrations/*` routes consume reusable bundle view-models/templates and require explicit managed vs BYOK choice before configuration:

- Ownership mode badge: cyan `managed` or violet `byok`
- Credential display: always `'********'` — raw values never rendered
- `custodySummary`: existing field name for the credential-handling owner summary (differs by mode)
- `supportContactLabel`: differs by mode (managed → platform support, BYOK → customer-managed)
- `capabilities`: same list per integration regardless of mode

- Security-class routes (`credentials`, `secrets`) are always `force-dynamic`; do not move them to static generation or cache rendered output.
- Rendered output, fixtures, snapshots, logs, and behavior signals may include only redacted credential references such as `********` or opaque `secretref://...` identifiers.
- The configure API route uses verified Better Auth context in production; `x-managed-companyos-session-id` is accepted only in local/test fixture mode. Anonymous and cross-site mutation attempts return deny responses.

## Degraded-state handling

Every page checks `shell.degradedBanner`:
- Present → renders an `aria-live="polite"` amber banner (`role="status"`) with the degraded reason
- Absent → no banner; normal render

`shell.stateCopy` provides all four state strings: `loading`, `empty`, `error`, `degraded`.

## Accessibility and responsiveness

- Page root: `aria-labelledby` tied to the `H1` `id`
- Navigation cards: `aria-label` on container and each article with health status
- Status badges: explicit `aria-label` (e.g. `"Ownership mode: managed"`, `"Health status: healthy"`)
- Degraded banner: `role="status"` + `aria-live="polite"`
- Responsive padding: `p-4 sm:p-8`; card widths: `w-full sm:w-64` or `w-full sm:w-80`
- No raw `<div>`, `<section>`, `<main>`, `<header>` — layout via design-system primitives only


## Vercel-only production readiness

The managed CompanyOS web monolith runs on Vercel with request-time/manual-refresh snapshots. Production pages consume bundle-owned `vercelSnapshot` readiness and API snapshot routes; they must not require browser WebSocket/SSE/EventSource connections, interval polling, or automatic polling to prove readiness.

Key operator expectations:

- Status and cockpit surfaces are request-time (`force-dynamic`) where readiness must reflect current API snapshots.
- Manual refresh/navigation is the only refresh affordance for the cost-capped topology.
- The bundle remains the source of truth for shell/view-model/status UI shapes.
- The standalone Bun realtime runtime is a non-production/future VPS mode, not a Vercel production dependency.
- Vercel functions run on the **Node.js** runtime (project setting `24.x`): `vercel.json` deliberately has no `bunVersion`. On the beta Bun runtime, a client that disconnected mid-stream kept the function open until the 300 s limit (`Task timed out after 300 seconds`). Bun still installs and builds the app. Evidence: `docs/evidence/opa/close-the-loop-deploy-3-2026-10-15.md`.

## Design-system rule

Use design-system primitives exclusively:

```ts
// Layout
import { Box, HStack, VStack } from '@lssm-tech/lib.design-system/components/layout';
// Typography
import { H1, H2, P, Text } from '@lssm-tech/lib.design-system/components/typography';
```


No raw HTML markup in app shells. No imports from `@radix-ui/*` or native-only packages in web-only files.

## Environment variables

Production must follow the environment contract in
`docs/runbooks/managed-companyos.md` [source link unresolved: `../../../docs/runbooks/managed-companyos.md`].
The API/auth origins must be exact HTTPS values, and production must fail closed
instead of falling back to localhost, a fixture URI, or a demo tenant.

| Variable | Purpose |
|---|---|
| `AUTH_PROVIDER_MODE` | `better-auth` in production; `fixture` is local/CI only. |
| `BETTER_AUTH_BASE_URL` | Exact server-side API/auth origin, `https://api.companyos.run`. |
| `LSSM_IDENTITY_WEB_PROFILE` | Identity web deployment only: set to `1` to enforce the exact `id.lssm.co` host and Passport-only route inventory. Omit from CompanyOS deployments. |
| `LSSM_IDP_UPSTREAM_API_ORIGIN` | Identity web deployment only: exact HTTPS origin of the reviewed Elysia identity API. Enables same-origin auth and discovery rewrites on `id.lssm.co`; omit from CompanyOS deployments. |
| `MANAGED_COMPANYOS_PROFILE_CONTEXT_SECRET` | Server-only HMAC key for profile context binding. Required in production and at least 32 bytes. |
| `MANAGED_COMPANYOS_INTEGRATION_TOPOLOGY_PROFILE` | Optional server-only deployment declaration for `/companyos/integrations/runtime`: `lssm_managed`, `vertical_managed`, `customer_hosted`, or `hybrid`. It never counts as provider proof. |
| `MANAGED_COMPANYOS_PUBLIC_BOOKING_ADAPTER_STATUS` | Leave unset for dry-run. `adapter_ready` is permitted only after the provider/vault evidence gate in `docs/runbooks/opa-public-booking.md`; it does not itself activate live traffic. |
| `NEXT_PUBLIC_BETTER_AUTH_BASE_URL` | Same API/auth origin for browser Better Auth calls and organization switching. |
| `NEXT_PUBLIC_MANAGED_COMPANYOS_API_BASE_URL` | API base URL for session-scoped request-time snapshots when web/API are deployed separately. |
| `NEXT_PUBLIC_MANAGED_COMPANYOS_DEFAULT_TENANT_ID` | Fixture/dev preview only. Leave empty in production; it is never organization or tenant authority. |

The `id.lssm.co` web profile exposes only the bounded Passport inventory,
including the authenticated `/auth/privacy` governed-share center:
account, sign-in, magic-link recovery, consent, invitation acceptance,
post-login access, resume, and private access administration. Unknown paths
return `404`, and a request carrying a foreign host returns `421`. Invitation
acceptance proxies only the bounded product-access endpoint to the reviewed
identity API. The access page never offers an OAuth continuation when
entitlement evidence is absent; it routes the person back to the relevant
product waitlist instead.

## Local commands

```bash
bun run --cwd packages/apps/web-application-monolith dev
bun run --cwd packages/apps/web-application-monolith test
bun run --cwd packages/apps/web-application-monolith typecheck
bun run --cwd packages/apps/web-application-monolith lint:check
bun run --cwd packages/apps/web-application-monolith build
```


For the full operator runbook (deploy, start/stop, degraded triage, replay regen, evidence verification), see `docs/runbooks/managed-companyos.md` [source link unresolved: `../../../../docs/runbooks/managed-companyos.md`].

## Local authenticated E2E lane (`bun run e2e:local`)

`bun run e2e:local` runs the logged-in journeys against a real local stack, with nothing reaching production, Google or a mail provider. It needs Docker and Playwright Chromium (`bunx playwright install chromium`).

```bash
cd packages/apps/web-application-monolith
bun run e2e:local                         # provision, run every spec, tear down
bun run e2e:local -- account.spec.ts      # extra args go to `playwright test`
E2E_LOCAL_REUSE_BUILD=1 bun run e2e:local # skip an identical `next build`
bun run e2e:local -- --stack-only         # keep the stack up for manual QA (Ctrl+C stops)
```


Each run (`tests-e2e/support/local-stack/run-local-stack.ts`):

1. starts a throwaway `postgres:16-alpine` container on a random loopback port (tmpfs, `--rm`; containers left by a crashed run are reaped next time) and generates every secret and persona password;
2. runs the API's own `local-test-lifecycle.ts reset` (migrate + seed + verify), `scripts/bootstrap-admin.ts` and `scripts/e2e-local/seed-e2e-local.ts` (fake connected Google calendar per canonical workspace with tokens in the encrypted OPA vault, the canonical booking surfaces, and the `member`, `account`, `security` and `signin` personas in `companyos`);
3. serves an in-memory Resend-compatible mail sink (`GET /mail.json?to=`) and ticks the API cron routes every 3 s (booking calendar writes, booking email, profile cache);
4. starts the API through `scripts/e2e-local/e2e-api-server.ts`, where the googleapis client is answered by a deterministic in-memory Google Calendar fake (every working-hours slot is free);
5. builds and serves the web app in production mode (`next build` + `next start`, dist dir `.next-e2e-local`) with every production-pointing value of the tracked `.env.local` overridden;
6. runs `playwright.local-stack.config.ts` (headless Chromium, `tests-e2e/local-stack/`, retries 1 on CI, traces/screenshots/video kept on failure, HTML report in `playwright-report/local-stack`).

| Port | Service | Override |
| --- | --- | --- |
| 3617 | web (`next start`) | `E2E_LOCAL_WEB_PORT` |
| 3618 | API | `E2E_LOCAL_API_PORT` |
| 3619 | mail sink | `E2E_LOCAL_MAIL_PORT` |

Run logs and the per-run manifest live in the gitignored `.e2e-local/<runId>/`; the manifest (it holds the generated passwords) is deleted at teardown. With `--stack-only`, point a separate `bunx playwright test -c playwright.local-stack.config.ts` at it with `E2E_LOCAL_STACK_MANIFEST=<printed manifestPath>`. Without a manifest every local-stack spec skips, and the default Playwright configs ignore `tests-e2e/local-stack/`.

The API runs with the test-only `COMPANYOS_AUTH_PROFILE=local-e2e-v1` auth topology (`@lssm-tech/lib.companyos-spec` `defineCompanyOsLocalE2eAuthTopology`): plain-HTTP loopback origins, host-only cookies. The readiness gate refuses it on `NODE_ENV=production`, any `VERCEL_ENV`/`RAILWAY_ENVIRONMENT`, a cookie domain, the LSSM IdP/RP flags or a non-loopback database. The CommunicationOS specs run without a CommunicationOS backend and check the degraded states. Helper checks: `bun run test:e2e-local-support` and `bun run typecheck:e2e-local`.


## Theme & runtime wiring

### CSS

`src/app/globals.css` bootstraps the CSS pipeline and provides the SSR-safe
fallback for `contractspec.design.executive-ledger@2.0.0`. The canonical palette
uses parchment, carbon, mineral blue, oxblood, and brass; dark mode has its own
carbon, bone, mineral, oxblood, and brass values. Newsreader, IBM Plex Sans, and
IBM Plex Mono are loaded through `next/font`.

### Theme provider

`src/app/providers.tsx` makes `next-themes` the sole light/dark/system authority.
The resolved mode is passed into `DesignSystemThemeProvider`; CSS variables are
applied only after mount, while the class-scoped fallback tokens keep the first
paint visible and consistent. CompanyOS defaults to Executive Ledger 2.0 while
the design-selection policy remains available for tenant/user preview.

### PostHog observability

`PostHogProvider` activates only when `NEXT_PUBLIC_POSTHOG_KEY` is set. When absent, no PostHog requests are made and the provider wrapper is omitted. SSR-safe: init runs inside `useEffect` with a `typeof window` guard. Browser capture uses `/ingest` while the PostHog UI host remains `https://eu.posthog.com`; `next.config.mjs` rewrites `/ingest` to `https://eu.i.posthog.com` and `/ingest/static` to EU assets. Server-side SDK capture uses `POSTHOG_HOST=https://eu.i.posthog.com`. When enabled, add `connect-src https://eu.i.posthog.com` to your CSP (S2 concern).

### Global state routes

| Route | File | Type | Notes |
|---|---|---|---|
| `/error` | `src/app/error.tsx` | Client Component | Error boundary — renders `stateCopy.error` + "Try again"; logs `error.digest` only |
| `/loading` | `src/app/loading.tsx` | Server Component | Renders `stateCopy.loading` with `role="status"` |
| `/not-found` | `src/app/not-found.tsx` | Server Component | Renders `stateCopy.empty` + home link |

### Enforcement tests

Three mechanical tests added in S1:
- **`src/__tests__/import-boundaries.test.ts`** — fails CI if `next-themes` or `@posthog/react` appear outside `layout.tsx` / `providers.tsx`.
- **`src/__tests__/raw-color-baseline.test.ts`** — asserts raw Tailwind color class count ≤ 391 (2026-05-16 baseline). S3 target: 0.
- **`src/__tests__/providers.test.tsx`** — asserts `posthog.init` is not called when `NEXT_PUBLIC_POSTHOG_KEY` is unset.

Test infra: `src/__tests__/setup-next-mocks.ts` stubs `next/font/google` for bun's test runner, preloaded via `bunfig.toml`.

## How to add a new route

1. **Define the nav item in bundle**: Create `NavSurfaceItemSpec` in `@lssm-tech/bundle.managed-companyos/src/web-shell.ts`
   ```typescript
   defineNavSurfaceItem({
     id: 'my-feature',
     route: { web: '/companyos/my-feature' },
     capability: { surface: 'navigation', key: 'companyos:my_feature:view' },
     groupKey: 'operations',
     iconKey: 'briefcase',
     densityHint: 'compact',
   })
   ```


2. **Register the capability**: Ensure the capability is registered in `CapabilityRegistry` with `surface: 'navigation'`

3. **Create the page**: `src/app/companyos/my-feature/page.tsx`
   ```typescript
   export const dynamic = 'force-static';

   export default function MyFeaturePage() {
     return <MyFeatureComponent />;
   }

   export const myFeaturePageDocBlock = {
     id: 'my-feature-page',
     title: 'My Feature Page',
     body: '...',
     kind: 'goal',
     route: 'packages/apps/web-application-monolith/src/app/companyos/my-feature/page.tsx',
     visibility: 'public',
   } satisfies DocBlock;
   ```


4. **Emit signals**: In your component, emit behavior signals on mount
   ```typescript
   useEffect(() => {
     const id = crypto.randomUUID();
     void emitCompanyOsBehaviorSignal({
       surfaceId: 'my_feature',
       signal: 'surface_viewed',
       correlationId: id,
       tenantId: 'demo',
       actorKind: 'founder_approver',
     });
   }, []);
   ```


5. **Verify**: `bun run lint:check && bun run lint:signals && bun run typecheck`

## How to add a new persona

1. **Document in PERSONAS.md** (repo root): Define persona responsibilities, default preferences (density/guidance/pace)

2. **Create the home page**: `src/app/companyos/{persona}/page.tsx`
   - Either wrap a candidate template (e.g., `FounderHome` wraps `MissionLandingFunnel`)
   - Or compose custom shell with nav items and module grid

3. **Register nav subset**: In bundle `web-shell.ts`, set `personaVisibility` on nav items
   ```typescript
   defineNavSurfaceItem({
     // ...
     personaVisibility: {
       founder_approver: true,
       operations_manager: false,
       // ...
     }
   })
   ```


4. **Update persona dispatcher**: Modify `/companyos/page.tsx` to route to new persona home

5. **Add E2E test**: Create Playwright test for persona happy-path (signin → home → navigate → signout)

## Thin app shell

This app follows the package-architecture layering rules [source link unresolved: `../../.claude/rules/package-architecture.md`]: apps stay thin by composing bundles, not owning shared UI.

Thin-shell rule is **active**. The `src/components/` directory is **intentionally absent** — all 427+ shared React components have been migrated to `packages/bundles/managed-companyos/src/ui/<domain>/` via PR series `chore/migration/slice-*` (Slices 1–13).

**Do not recreate `src/components/`.** All shared UI belongs in the bundle's `./ui` subpath, imported as `@lssm-tech/bundle.managed-companyos/ui` or `@lssm-tech/bundle.managed-companyos/ui/<domain>`. Boundary rules enforce this at error level in CI.

## Integration Points

### Embedding Managed CompanyOS Surfaces

The web app exposes individual screens as React Server Components that can be embedded in other Next.js applications:

```typescript
import { CompanyOsOnboarding } from '@lssm-tech/app.web-application-monolith/companyos/onboarding';

// Embed in another app's page
export default function AdminPanel() {
  return <CompanyOsOnboarding tenantId="tenant_xyz" />;
}
```


Each screen route (`/companyos/*`) is independently renderable and passes tenant context through layout context/props.

### API Dependency

All screens fetch data from the API app via fetch:

```typescript
// Inside a screen component
const response = await fetch('/api/companyos/workspace', {
  headers: { 'x-managed-companyos-session': sessionToken }
});
const workspace = await response.json();
```


The web app assumes the API is available at the same origin. For separate deployments, override `NEXT_PUBLIC_MANAGED_COMPANYOS_API_BASE_URL` env var.

### Manual snapshot refresh

Screens render request-time snapshots from the API/bundle seam. Operators and users refresh by navigating or manually refreshing the page; the app must not introduce WebSocket, SSE, EventSource, interval polling, or automatic polling for managed CompanyOS production readiness.

For separate web/API deployments, configure `NEXT_PUBLIC_MANAGED_COMPANYOS_API_BASE_URL` and keep session authority on the API side.

### MCP Integration

For AI agents and CLI tools that need to read Managed CompanyOS state without opening the web UI, use the planned `@lssm-tech/app.managed-companyos-mcp` server. It exposes tenant graph queries, approval lists, replay packets, and evidence receipts as MCP tools and resources.

## Environment

Copy `deploy/env/web.env.example` into the deployment secret-manager backed environment group. Public values may identify API endpoints, but raw provider credentials never belong in web env files.

- Set `NEXT_PUBLIC_POSTHOG_KEY` only when browser analytics are intended.
- Set server `POSTHOG_HOST` to EU Cloud capture: `https://eu.i.posthog.com`.
- Omit `DATABASE_URL` unless a dedicated least-privilege/read-only proof credential exists; never use the API admin/migrator Supabase URL in the web project.

The OPA web proxy forwards the declared capture/consent routes with fresh session
authority and same-origin mutation checks. Chunk uploads have a 1,410,000-byte
JSON transport limit; other requests retain the 128 KiB limit. Both are enforced
while streaming, including requests without a Content-Length header.

### Private reviewed meeting outcomes

The existing meeting-workspace routes accept `x-opa-owner-view: private` to derive individual ownership from the verified user within the selected workspace. Omitting the header preserves context ownership; arbitrary owner selectors are rejected. Use the same private view for outcome analysis and subsequent artifact reads. The web BFF forwards this selector after its existing authentication and mutation-origin checks.

CompanyOS outcome analysis loads the persisted approved transcript review, verifies exact source and review bindings, and checks current `intelligence.generate` policy before generation and commit. Rejected, changed, unauthorized or workspace-widened sources fail closed. The adapter uses the caller transaction and does not publish private capture text. Model calls run outside aggregate transactions. Finalization reloads current state and rechecks authority and the reviewed source before saving. Durable outcome jobs are available behind explicit configuration; downstream effects and live quality qualification remain open.

### Reviewed outcome drafts in CompanyOS

The approved transcript panel can generate and read private meeting drafts through existing OPA operations. Generation controls use server-derived `canGenerateOutcomes`; authority and automation policy are rechecked server-side. Draft generation creates no messages or Work tasks. French, English and Spanish copy distinguishes loading, generation, retry, denied access and empty history.

Artifact list 2.2.0 accepts optional `reviewRef`, selecting the current review before source reproof so stale historical drafts do not block current results. Transcript get 2.2.0 adds the generation capability projection. The client pins private ownership and an exact review-derived retry key, including across reloads. Interactive generation has a bounded 180-second request deadline; the web proxy allows a 300-second function budget. Persisted background jobs, signed-native presentation and full browser/accessibility qualification remain incomplete.

### Durable outcome processing

Analyze 3.1.0 accepts `executionMode: background` on its existing route. Repeating the exact request observes the same persisted job; processing responses carry `processingJobRef`, while completion returns the saved outcome. The private draft client selects background mode when the server advertises it and can stop polling without cancelling accepted work. Terminal failures remain failures.

Apply additive migration 0080, configure a dedicated `companyos_outcome_dispatcher` login, and enable `OPA_OUTCOME_JOBS_ENABLED=1` only with approved pinned `OPA_MEETING_AI_*` EU processing. The every-minute `/api/cron/opa-outcome-processing` route requires `CRON_SECRET`. Runtime credentials must not be superuser, BYPASSRLS or a member of `opa_migrator`. The queue admits four global jobs and one per owner, bounds pending owner jobs at 25, retries at most five times and uses six-minute fenced leases. Current membership, module entitlement, intelligence policy, source consent/review and model binding are rechecked before generation and commit.

Outcome persistence and completion share a transaction; model calls are outside SQL. Queue rows contain references and authorization evidence, not transcript text or credentials. Model cost may repeat after a crash before commit. Terminal-job self-service repair, queue retention/deletion propagation, live model/provider qualification and production rollout remain open. No production activation is implied by the local tests.

### Approved action to canonical Work

`opa.task.project` 3.0.0 projects one approved structured action through the existing task route. The request binds artifact revision/digest, approval receipt, action reference and selected workspace. It requires explicit workspace disclosure acknowledgment and confirmation for an uncertain proposal. The UI exposes this action only for approved task lists and server-derived projection permission.

Only the reviewed title and details are transferred; raw/private transcript text and source quotes are not copied into Work. Assignees and deadlines remain unset. Current `outcome.commit` policy, transcript review/consent and Work workspace write authority are rechecked. Work event/idempotency/outbox and the OPA projection receipt commit in one transaction. Repeated projection returns the existing Work object; a receipt represents committed task creation, not task completion or realtime projection convergence.

New owner capability manifests include `opa.task.project`; existing grants require an authorized update and are not silently widened. Legacy input-only projection clients must update to 3.0.0. CommunicationOS delivery, assignment/due-date controls, real-authority deployment qualification and full release gates remain open.

### Better Auth 1.7 callback forwarding

The existing public LSSM callback alias forwards only its bounded authorization
response to the fixed API owner's `/auth/callback/` endpoint, replacing the
removed `/auth/oauth2/callback/` path. Existing issuer and parameter checks remain
in force. API token exchange, provider registrations, cookies and account-identity
migration still require live qualification before cutover.

TOTP enrollment explicitly requests `method: totp` and rejects a different result.
Unlink requires a specific linked account and resolves its unique current provider
mapping before sending Better Auth's stored account ID. Missing or ambiguous
mappings fail before the unlink request.

### Memory import transport

`createAgentMemoryImportClient` wires prepared import references to a configured
Agent Host origin. It requires HTTPS except for loopback development, sends an
explicit short-lived bearer credential, disallows redirects and automatic retries,
and validates the response proposal digest. Lost responses and timeouts remain
indeterminate. The client does not prepare work orders, upload memory contents,
store tokens or grant authority. Route composition must supply reviewed prepared
requests and obtain credentials through the application's authenticated session.

The `/api/companyos/builder/*` web bridge exposes existing authoring operations
through same-origin session requests. It does not expose release execution.
The API retains capability and tenant enforcement; uncertain mutations are not
automatically retried. Configure `MANAGED_COMPANYOS_API_BASE_URL` for the API host.

The Builder Sources tab can query company context through the authenticated BFF.
The host must configure the API grounding service before retrieval is available;
an unconfigured service is presented explicitly. Requests are member-triggered,
bounded, and never automatically replayed. Changing workspace clears the view
and ignores responses from the previous workspace. Retrieved evidence is text
for review and cannot grant permission to ship.

The Builder workbench client submits intent, blueprint, plan, preview and readiness
actions through the authoring bridge. Confirmed writes refresh server-owned data;
unknown outcomes block further mutations for reconciliation. Page-level session
loading and deployment activation remain separate integration requirements.

`/companyos/builder` now offers explicit workspace creation; `?workspace=<id>`
loads saved state after session resolution and tenant/workspace checks. Lost
creation responses retain a workspace recovery link. This is an authoring pilot,
not proof that production deployment actions are activated.

Member creation returns an opaque, context-bound workspace ID. Recovery may use
the original request ID; the loader accepts the API's explicit matching resolution
receipt and still verifies tenant identity and snapshot structure. Missing grants
or a changed company/team/workspace context deny access. The API must have the
pilot's exact authoring grants configured before this journey is usable.

For `COMPANYOS_AUTH_PROFILE=preview-v1`, configure the same explicit
`COMPANYOS_PREVIEW_WEB_ORIGIN` and `COMPANYOS_PREVIEW_API_ORIGIN` as the API. The web
app's `NEXT_PUBLIC_BETTER_AUTH_BASE_URL` equals the web origin, while server-side
`BETTER_AUTH_BASE_URL` and `MANAGED_COMPANYOS_API_BASE_URL` equal the API origin.
Auth and enumerated context endpoints are rewritten to that API. Never add a
broad `/api/companyos/*` afterFiles rewrite: it runs before dynamic BFF routes
and would bypass Builder session mediation.
Do not inherit `LSSM_IDP_UPSTREAM_API_ORIGIN` or select preview on a production
Vercel deployment. The API target must admit the web proxy under its configured
access controls; a build-ready deployment alone does not prove login works.
Authentication callbacks resolve against this configured preview origin. Builder
sign-in retains its workspace return path rather than sending the member to a
different environment or losing the work item.

The login page uses configured API login-method discovery for email-code and magic-link controls. When discovery is unavailable, delivery controls are omitted; password login remains available. Password reset is shown only when an email delivery method is configured.

Edge cookie presence and server session-token forwarding both select the configured
profile prefix. Preview cookies are not accepted as production cookies or vice
versa; the API still validates the session and current authority.

Builder workbench mounts its existing locale catalog locally, delegating non-Builder
keys to the parent application runtime. No duplicate translation strings are defined.

Builder BFF responses expose numeric Server-Timing phases: auth, input, upstream
(response headers), and total. Streamed response-body time is excluded. Compare
these with client elapsed time before changing deadlines; uncertain writes remain
non-retryable until their saved outcome is reconciled.

After an uncertain workbench mutation, “Check saved workspace” reloads server-owned
state without repeating the write. Inspect that state before submitting another action.

Builder company context is available through the host-owned
`builder.companyContext.resolve` query and POST
`/api/companyos/builder/context/resolve`. It accepts an owned workspace ID and
a nonempty question up to 4096 UTF-8 bytes. Missing grounding configuration
returns 503. The web BFF preserves authentication and response status; the
client treats this as a query, never a saved mutation, and does not auto-retry.
Context grants no execution authority. Provider configuration, a visible
member control and live qualification remain required before advertising it.

Public booking isolates client state by booking token and embed origin. Refresh responses are revision-guarded: an older request or an unmounted session cannot replace current availability or emit ready/error callbacks. This does not qualify provider availability or durable booking effects.


Public booking routes use booking-specific localized loading text. LINK_NOT_FOUND offers guidance to request a replacement link; temporary availability failures retain retry. Refresh fencing preserves typed failures without letting stale requests replace current state.

Committed CompanyOS organization/workspace switches synchronously unmount the previous shell and private content before document reload. If reload fails or returns, the cleared transition screen remains; its localized Reload workspace action retries only the document reload and never restores the previous context. This protects committed selector changes, not remote revocation events that the host has not observed.

## Builder candidate journey

The Builder Plan tab exposes Prepare candidate, Approve candidate, Run candidate
and Check status through the existing authenticated BFF. Requests carry the
reviewed plan reference and an idempotency correlation ID, never provider
credentials or caller-selected authority. Responses are scope/digest checked;
uncertain effects are not retried automatically. Queued/running work receives
up to twenty status refreshes at three-second intervals, then remains manually
refreshable. Workspace or plan changes discard stale responses.

The API must install the concrete candidate service before execution becomes
available. The separate export controls remain unconnected to actual export
effects; candidate completion never implies a deployed preview or shipped release.

## Build compute policy

Automatic Vercel Git builds are disabled for this app. Build compute is assigned
to Railway; this does not change the existing runtime or domain topology.
See the operator policy and evidence [source link unresolved: `../../../deploy/lssm-ecosystem/build-compute-policy.md`]
for configuration scope and the unqualified Vercel prebuilt delivery gap.


### Source links needing reconciliation

- `../../../docs/runbooks/opa-smart-meeting.md` — source path absent from pinned inventory: docs/runbooks/opa-smart-meeting.md.
- `../../../docs/evidence/authos/decommission-hirly-ndconsulting-2026-10-20.md` — source path absent from pinned inventory: docs/evidence/authos/decommission-hirly-ndconsulting-2026-10-20.md.
- `../../../docs/runbooks/special-ops-monolith-production.md` — source path absent from pinned inventory: docs/runbooks/special-ops-monolith-production.md.
- `../../../docs/runbooks/managed-companyos.md` — source path absent from pinned inventory: docs/runbooks/managed-companyos.md.
- `../../../docs/runbooks/real-organizations-rollout.md` — source path absent from pinned inventory: docs/runbooks/real-organizations-rollout.md.
- `../../../docs/runbooks/companyos-seo-discovery.md` — source path absent from pinned inventory: docs/runbooks/companyos-seo-discovery.md.
- `../../../../docs/runbooks/managed-companyos.md` — source path absent from pinned inventory: ../docs/runbooks/managed-companyos.md.
- `../../.claude/rules/package-architecture.md` — source path absent from pinned inventory: packages/.claude/rules/package-architecture.md.
- `../../../deploy/lssm-ecosystem/build-compute-policy.md` — source path absent from pinned inventory: deploy/lssm-ecosystem/build-compute-policy.md.

## Declared capabilities

This manifest does not declare a capability catalogue. Assess the package using its guide, import map and source.

## Catalogue metadata

```json
{
  "visualTesting": {
    "status": "deferred",
    "owner": "@contractspec-core",
    "targetWave": "wave-2-core-ui",
    "rationale": "Foundational Storybook adoption establishes shared catalogs and guardrails before this package migrates."
  }
}
```

## Canonical imports

Import paths and symbols below are catalogue declarations. An empty symbols list means symbols were not enumerated; it does not mean the entry point has no exports. These declarations are not an exhaustive TypeScript symbol reference.

```json
[]
```

## Declared export entry points

Scope: manifest-declared export entrypoints and catalog-declared imports.

Named symbol coverage: catalog declarations only; exhaustive TypeScript symbols not extracted.

Installation status: not verified.

- `@lssm-tech/app.web-application-monolith` — subpath `.`
  - `unconditional`: `./src/index.ts` — [pinned source](https://github.com/lssm-tech/contractspec/blob/bcc79fcc27c4d801c2119bef81ddcce7b4e86498/packages/apps/web-application-monolith/src/index.ts); verified source file.

## Package publication metadata

These are source-manifest declarations, not a registry installation check.

```json
{
  "types": null,
  "files": null,
  "publishExports": null
}
```

## Dependencies

Metadata status: complete pinned manifest.

### Runtime dependencies

- `@fontsource/ibm-plex-mono`: `5.3.0`
- `@fontsource/ibm-plex-sans`: `5.3.0`
- `@fontsource/newsreader`: `5.3.0`
- [@lssm-tech/bundle.managed-companyos](https://lssm.co/docs/packages/bundle.managed-companyos/): `workspace:*`
- [@lssm-tech/bundle.marketing](https://lssm.co/docs/packages/bundle.marketing/): `workspace:*`
- [@lssm-tech/bundle.marketing-operations](https://lssm.co/docs/packages/bundle.marketing-operations/): `workspace:*`
- [@lssm-tech/integration.authos-better-auth](https://lssm.co/docs/packages/integration.authos-better-auth/): `workspace:*`
- [@lssm-tech/integration.communication-os-client](https://lssm.co/docs/packages/integration.communication-os-client/): `workspace:*`
- [@lssm-tech/integration.communication-os-host-auth](https://lssm.co/docs/packages/integration.communication-os-host-auth/): `workspace:*`
- [@lssm-tech/integration.integration-topology-evidence-postgres](https://lssm.co/docs/packages/integration.integration-topology-evidence-postgres/): `workspace:*`
- [@lssm-tech/integration.provider-database](https://lssm.co/docs/packages/integration.provider-database/): `workspace:*`
- [@lssm-tech/integration.providers-impls](https://lssm.co/docs/packages/integration.providers-impls/): `workspace:*`
- [@lssm-tech/integration.runtime-managed](https://lssm.co/docs/packages/integration.runtime-managed/): `workspace:*`
- [@lssm-tech/lib.authos-runtime](https://lssm.co/docs/packages/lib.authos-runtime/): `workspace:*`
- [@lssm-tech/lib.authos-spec](https://lssm.co/docs/packages/lib.authos-spec/): `workspace:*`
- [@lssm-tech/lib.builder-spec](https://lssm.co/docs/packages/lib.builder-spec/): `workspace:*`
- [@lssm-tech/lib.communication-spec](https://lssm.co/docs/packages/lib.communication-spec/): `workspace:*`
- [@lssm-tech/lib.content-gen](https://lssm.co/docs/packages/lib.content-gen/): `workspace:*`
- [@lssm-tech/lib.contracts-integrations](https://lssm.co/docs/packages/lib.contracts-integrations/): `workspace:*`
- [@lssm-tech/lib.contracts-runtime-client-react](https://lssm.co/docs/packages/lib.contracts-runtime-client-react/): `workspace:*`
- [@lssm-tech/lib.contracts-runtime-core](https://lssm.co/docs/packages/lib.contracts-runtime-core/): `workspace:*`
- [@lssm-tech/lib.contracts-spec](https://lssm.co/docs/packages/lib.contracts-spec/): `workspace:*`
- [@lssm-tech/lib.crypto-utils](https://lssm.co/docs/packages/lib.crypto-utils/): `workspace:*`
- [@lssm-tech/lib.data-exchange-core](https://lssm.co/docs/packages/lib.data-exchange-core/): `workspace:*`
- [@lssm-tech/lib.design-catalog](https://lssm.co/docs/packages/lib.design-catalog/): `workspace:*`
- [@lssm-tech/lib.design-system](https://lssm.co/docs/packages/lib.design-system/): `workspace:*`
- [@lssm-tech/lib.founder-intelligence-spec](https://lssm.co/docs/packages/lib.founder-intelligence-spec/): `workspace:*`
- [@lssm-tech/lib.observability](https://lssm.co/docs/packages/lib.observability/): `workspace:*`
- [@lssm-tech/lib.organization-planning-spec](https://lssm.co/docs/packages/lib.organization-planning-spec/): `workspace:*`
- [@lssm-tech/lib.personalization](https://lssm.co/docs/packages/lib.personalization/): `workspace:*`
- [@lssm-tech/lib.presentation-runtime-core](https://lssm.co/docs/packages/lib.presentation-runtime-core/): `workspace:*`
- [@lssm-tech/lib.presentation-runtime-next](https://lssm.co/docs/packages/lib.presentation-runtime-next/): `workspace:*`
- [@lssm-tech/lib.presentation-runtime-react](https://lssm.co/docs/packages/lib.presentation-runtime-react/): `workspace:*`
- [@lssm-tech/lib.surface-runtime](https://lssm.co/docs/packages/lib.surface-runtime/): `workspace:*`
- [@lssm-tech/lib.translation-runtime](https://lssm.co/docs/packages/lib.translation-runtime/): `workspace:*`
- [@lssm-tech/lib.ui-kit-core](https://lssm.co/docs/packages/lib.ui-kit-core/): `workspace:*`
- [@lssm-tech/lib.ui-kit-web](https://lssm.co/docs/packages/lib.ui-kit-web/): `workspace:*`
- [@lssm-tech/module.agent-fleet](https://lssm.co/docs/packages/module.agent-fleet/): `workspace:*`
- [@lssm-tech/module.app-submission-readiness](https://lssm.co/docs/packages/module.app-submission-readiness/): `workspace:*`
- [@lssm-tech/module.auth-os](https://lssm.co/docs/packages/module.auth-os/): `workspace:*`
- [@lssm-tech/module.builder-workbench](https://lssm.co/docs/packages/module.builder-workbench/): `workspace:*`
- [@lssm-tech/module.communication-os](https://lssm.co/docs/packages/module.communication-os/): `workspace:*`
- [@lssm-tech/module.customer-support](https://lssm.co/docs/packages/module.customer-support/): `workspace:*`
- [@lssm-tech/module.design-studio](https://lssm.co/docs/packages/module.design-studio/): `workspace:*`
- [@lssm-tech/module.governance-suite](https://lssm.co/docs/packages/module.governance-suite/): `workspace:*`
- [@lssm-tech/module.review-queue](https://lssm.co/docs/packages/module.review-queue/): `workspace:*`
- [@lssm-tech/opa-booking-react](https://lssm.co/docs/packages/opa-booking-react/): `workspace:*`
- `@opentelemetry/api`: `^1.9.1`
- `@opentelemetry/sdk-trace-base`: `^2.10.0`
- `@posthog/react`: `^1.11.1`
- `@vercel/analytics`: `2.0.1`
- `autoprefixer`: `^10.6.1`
- `better-auth`: `1.7.5`
- `lucide-react`: `catalog:ui`
- `next`: `catalog:`
- `next-themes`: `^0.4.6`
- `posthog-js`: `^1.434.0`
- `posthog-node`: `^5.51.7`
- `react`: `catalog:`
- `react-dom`: `catalog:`
- `tailwind-merge`: `catalog:ui`
- `tailwindcss-animate`: `catalog:ui`
- `zod`: `catalog:`

### Peer dependencies

No declarations in the inspected manifest.

### Optional dependencies

No declarations in the inspected manifest.

### Development dependencies

- `@axe-core/playwright`: `^4.13.0`
- [@lssm-tech/tool.typescript](https://lssm.co/docs/packages/tool.typescript/): `workspace:*`
- `@playwright/test`: `^1.63.0`
- `@tailwindcss/postcss`: `4.3.3`
- `@types/node`: `catalog:types`
- `@types/react`: `catalog:types`
- `@types/react-dom`: `catalog:types`
- `axe-core`: `^4.13.0`
- `dependency-cruiser`: `^18.3.1`
- `happy-dom`: `catalog:testing`
- `postcss`: `catalog:build`
- `postcss-load-config`: `^6.0.1`
- `tailwindcss`: `catalog:build`
- `tw-animate-css`: `1.4.0`
- `typescript`: `catalog:`

### Peer dependency metadata

```json
{}
```

### Bundled dependencies

```json
null
```

## Package scripts

Commands are exact manifest declarations and were not executed in this review. Script metadata status: complete pinned manifest.

```json
{
  "clean": "rm -rf dist .turbo",
  "build": "NODE_ENV=production bun --bun next build",
  "dev": "bun --bun next dev",
  "start": "NODE_ENV=production bun --bun next start",
  "lint": "bun run lint:fix",
  "lint:fix": "node ../../../scripts/biome.cjs check --write --unsafe --only=nursery/useSortedClasses . && node ../../../scripts/biome.cjs check --write .",
  "lint:check": "git ls-files -co -z --exclude-standard -- . ':!next-env.d.ts' | xargs -0 node ../../../scripts/biome.cjs check",
  "lint:privacy": "bun run scripts/lint-privacy-signals.ts",
  "lint:emitters": "bun scripts/lint-page-emitters.ts",
  "lint:no-debt": "bun scripts/lint-no-debt.ts",
  "lint:dev-toolbox-boundary": "depcruise --config .dependency-cruiser.cjs src/",
  "test": "bun test --isolate && bun test ./tests-e2e/support",
  "test:e2e": "playwright test",
  "e2e:local": "bun tests-e2e/support/local-stack/run-local-stack.ts",
  "test:e2e:runtime-topology": "playwright test --config playwright.runtime-topology.config.ts",
  "test:journeys": "playwright test -c tests-e2e/journeys/playwright.config.ts",
  "typecheck": "bun --bun x tsgo --project tsconfig.build.json --noEmit",
  "typecheck:e2e": "bun --bun x tsgo --project tsconfig.e2e.json --noEmit",
  "typecheck:e2e-local": "bun --bun x tsgo --project tsconfig.e2e-local.json --noEmit",
  "test:e2e-local-support": "bun test ./tests-e2e/support",
  "release:check-ux": "bun run scripts/check-ux-copy.ts",
  "prebuild": "bun --bun x tsgo --project tsconfig.build.json --noEmit",
  "companyos:builder:e2e": "bun test src/next-app.test.tsx",
  "experience:coverage": "bun run scripts/generate-experience-coverage.ts"
}
```

## Declared documentation links

No additional documentation links are declared in the inspected catalogue.

## Existing agent-guide projection

```json
{
  "path": "packages/apps/web-landing/public/llms-packages/app.web-application-monolith.txt",
  "route": "/llms/app.web-application-monolith",
  "sourceUrl": "https://github.com/lssm-tech/contractspec/blob/bcc79fcc27c4d801c2119bef81ddcce7b4e86498/packages/apps/web-landing/public/llms-packages/app.web-application-monolith.txt",
  "blobSha": "067a6307a59cc9737f2ae68b082c4499adc42516",
  "sourcePin": "bcc79fcc27c4d801c2119bef81ddcce7b4e86498",
  "bodyEqualsReadme": true,
  "aggregateSourcePath": "packages/apps/web-landing/public/llms-full.txt",
  "aggregateBlobSha": "691b1d33efee24c440598b9106c81432f56aafaf"
}
```
