Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
72e0711
Add non-secret workspace maintenance identifiers
MajorIncident Oct 8, 2026
a5dbd16
Add Admin maintenance API and lifecycle repository
MajorIncident Oct 8, 2026
b3bbb41
Expose single Admin maintenance function
MajorIncident Oct 8, 2026
c0c0428
Test Admin maintenance authorization and purge previews
MajorIncident Oct 8, 2026
274bd82
Account for single Admin serverless entrypoint
MajorIncident Oct 8, 2026
aa573a9
Add Administration Maintenance browser controller
MajorIncident Oct 8, 2026
4f245e5
Add Administration Maintenance interface
MajorIncident Oct 8, 2026
1245807
Align Admin auth form binding
MajorIncident Oct 8, 2026
6b8ff33
Initialize Administration Maintenance surface
MajorIncident Oct 8, 2026
ff36aea
Style Administration Maintenance console
MajorIncident Oct 8, 2026
526b87f
Cover Admin maintenance browser lifecycle
MajorIncident Oct 8, 2026
5542974
Document Administration Maintenance lifecycle contract
MajorIncident Oct 8, 2026
fb6a7d6
Point Admin work to maintenance contract
MajorIncident Oct 8, 2026
01036df
Document Admin maintenance security boundary
MajorIncident Oct 8, 2026
f501c95
Document Admin maintenance runtime and environment
MajorIncident Oct 8, 2026
e2675b5
Add Admin maintenance API guardrails
MajorIncident Oct 8, 2026
d5262a2
Map Admin maintenance modules for cold starts
MajorIncident Oct 8, 2026
ea6b014
Add Admin maintenance to architecture map
MajorIncident Oct 8, 2026
536e491
Register Admin maintenance feature anchors
MajorIncident Oct 8, 2026
371886f
Advance hardening plan to active Admin slice
MajorIncident Oct 8, 2026
ce9cb56
Checkpoint active #329 Admin maintenance work
MajorIncident Oct 8, 2026
63bd9e0
Recognize session-only UI in state guards
MajorIncident Oct 8, 2026
187d015
Recognize session-only UI in state guards
MajorIncident Oct 8, 2026
ddae8a6
Document session-only Admin controls
MajorIncident Oct 8, 2026
2556616
Fix Admin auth visibility and focus return
MajorIncident Oct 8, 2026
eaaca33
Mark Admin controls as session-only
MajorIncident Oct 8, 2026
3a8881e
Exclude Admin recovery value from Intake state
MajorIncident Oct 8, 2026
1ffd2db
Advance roadmap to active Admin lifecycle
MajorIncident Oct 8, 2026
6890783
Link Classroom architecture to Admin maintenance contract
MajorIncident Oct 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ See `docs/REPOSITORY-OPERATIONS.md#delivery-resilience-for-ai-assisted-work` for

## Long-running Classroom Program

The Standalone / Student / Instructor program is tracked by #288. Any work touching experience roles, classes, classroom workspaces, instructor observation, coaching, or protected Case Studies must read `docs/classroom-architecture.md`, `docs/classroom-roadmap.md`, and `docs/classroom-workstream.md` before editing. Class/API authorization work must additionally read `docs/classroom-api.md` and `api/AGENTS.md`. Staged exercise/debrief work under #313 must also read `docs/classroom-staged-simulation.md`. Work on universal Intake target identity, dynamic coaching targets, staged `intakeTargetIds`, or #319 debrief comparison must also read `docs/intake-target-identity.md`; that contract forbids template IDs and DOM selectors from becoming semantic target identity. Work on #328–#330, legacy credential/save cleanup, Administration/Maintenance, retention/purge behavior, or startup/resume routing must also read `docs/preproduction-hardening.md`; until #328 lands, legacy-path documentation may describe current runtime behavior even though the approved target is to remove that compatibility before public production.
The Standalone / Student / Instructor program is tracked by #288. Any work touching experience roles, classes, classroom workspaces, instructor observation, coaching, or protected Case Studies must read `docs/classroom-architecture.md`, `docs/classroom-roadmap.md`, and `docs/classroom-workstream.md` before editing. Class/API authorization work must additionally read `docs/classroom-api.md` and `api/AGENTS.md`. Staged exercise/debrief work under #313 must also read `docs/classroom-staged-simulation.md`. Work on universal Intake target identity, dynamic coaching targets, staged `intakeTargetIds`, or #319 debrief comparison must also read `docs/intake-target-identity.md`; that contract forbids template IDs and DOM selectors from becoming semantic target identity. Work on #328–#330, legacy credential/save cleanup, Administration/Maintenance, retention/purge behavior, or startup/resume routing must also read `docs/preproduction-hardening.md`. Work on #329, `/api/admin`, `INTAKE_ADMIN_TOKEN`, maintenance inventory, Instructor recovery, or physical purge must additionally read `docs/admin-maintenance.md`; Admin is not an experience role and destructive cleanup remains preview-first.

Classroom invariants:

Expand Down
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ KT Intake is a browser-first Kepner–Tregoe (KT) incident workbook designed for
## Quickstart
- Clone or download this repository.
- Open `index.html` in any modern browser. Standalone use remains local-first and does not depend on the classroom backend.
- A genuinely new browser asks whether to **Work independently**, **Join a class**, or **Teach a class**. Existing saved Intakes and existing `?workspace=` collaboration links migrate silently to **Standalone** so the new chooser does not interrupt established workflows.
- A browser with no current experience preference asks whether to **Work independently**, **Join a class**, or **Teach a class**. Existing explicit `?workspace=` collaboration links still route to **Standalone**; saved Intake data by itself no longer silently chooses an experience.
- The selected experience resumes from the separate `kt-experience-role-v1` preference. Intake work itself still loads from `kt-intake-full-v2`, with action plans under `kt-actions-by-analysis-v1`.
- Use the header controls to **Save to File** (exports a JSON snapshot) or **Load from File** (imports a previously saved snapshot) when you need to move an intake between browsers or machines.
- Open the shared resource drawer to work with curated material. **Standalone** receives public Standard Templates only. Connected **Students** receive Standard Templates plus Classroom-authorized Case Studies; connected **Instructors** receive authorized teaching Case Studies. The rotating Case Study mode password remains a learning/progression control, not authentication.
Expand All @@ -29,6 +29,10 @@ AI contributors should run the following commands (or manual preview) whenever t
| `npm run quality` | Before marking any pull request ready. | Canonical repository gate: lockfile, repo doctor, domain guards, lint, generated-file freshness, protected-case boundary, storage docs, and the full test suite. See [`docs/REPOSITORY-OPERATIONS.md`](docs/REPOSITORY-OPERATIONS.md). |
| `npm run update:storage-docs` / `npm run check:storage-docs` | Run `update` whenever you alter persisted schema, then `check` before pushing. | Keeps [`docs/storage-schema.md`](docs/storage-schema.md) and [`docs/storage-schema.appendix.md`](docs/storage-schema.appendix.md) synced with new keys or shapes. |

## Administration environment

Production Administration / Maintenance is fail-closed until a 43-character URL-safe 256-bit `INTAKE_ADMIN_TOKEN` is configured in the Vercel project environment. The value is server-only and must not be committed to this repository. See [`docs/admin-maintenance.md`](docs/admin-maintenance.md).

## Entry Point & Boot Logic
- `index.html` declares the full UI layout and loads the JavaScript bundle via `<script type="module" src="main.js"></script>`.
- `main.js` waits for `DOMContentLoaded`, then calls `boot()`. This bootstraps every feature in order:
Expand Down Expand Up @@ -62,6 +66,7 @@ See [`docs/architecture-overview.md`](docs/architecture-overview.md) for the boo
| `src/coachableFields.js` | Backward-compatible coaching facade over `src/intakeTargets.js`; preserves existing coaching export names and stored target IDs without owning a second registry. |
| `src/classroomCoaching.js` | Instructor coaching controls and Student read-only feedback UI backed by the separate Classroom coaching API. |
| `src/classroomCaseStudies.js` | In-memory authorized Classroom Case Study catalog/payload client. It receives active Student/Instructor capabilities from their lifecycle controllers and never persists them. |
| `src/adminMaintenance.js` | Privileged Administration / Maintenance UI. Keeps the verified Admin key only in tab-scoped `sessionStorage`, renders lifecycle inventory, performs Instructor recovery, and enforces preview-before-purge through `/api/admin`. |
| `main.js` | Entry point that imports every module, wires shared events, and runs `boot()`. |

### Storage keys
Expand All @@ -71,13 +76,16 @@ See [`docs/architecture-overview.md`](docs/architecture-overview.md) for the boo
- `kt-classroom-student-session-v1`: Student same-device resume key. Its current v2 envelope contains the stable Student class-session capability plus public class/participant/current-assignment context; the assignment-specific workspace capability remains memory-only and is reacquired after reload or reassignment. Older envelope formats are intentionally unsupported before production. The envelope never enters Intake exports/summaries/templates.
- `kt-classroom-student-local-recovery-v1`: Local recovery snapshot captured immediately before joining a class so **Leave class** can restore the prior local Intake. It is separate from the active Intake snapshot and classroom credentials.
- `kt-classroom-instructor-session-v1`: Local-only Instructor same-device resume envelope containing the Instructor class capability, public class metadata, and the last selected public workspace ID. It is never collected into Intake state, files, summaries, templates, or Student workspace credentials.
- `kt-admin-session-v1`: Tab-scoped Administration / Maintenance credential envelope stored in `sessionStorage` only after successful server verification. It is never written to localStorage or Intake state and disappears when the tab session ends or Admin signs out.

Coaching feedback is server-side Classroom data, not a local Intake storage key. It lives in `classroom_coaching_feedback` and is deliberately excluded from `kt-intake-full-v2`, Save/Load, templates, summaries, and collaboration snapshot revisions.

## Experience roles

Experience role is a product-level choice, not an Intake workflow mode. General / IT / Pharma / Major Incident remain controlled by `meta.intakeMode`; Standalone / Student / Instructor are controlled separately by `src/experienceRoles.js` and `src/experienceRoleController.js`.

**Administration / Maintenance is not an experience role.** It is a separate privileged utility entered from the chooser or View menu and authorized only by the server-configured `INTAKE_ADMIN_TOKEN`. See [`docs/admin-maintenance.md`](docs/admin-maintenance.md).

- **Standalone** exposes the normal Intake and current collaboration behavior. Its resource drawer contains **Templates only**.
- **Student** joins with a display name and one human class code. An Instructor share/QR link may prefill that same code through a client-only `#join=` fragment; the fragment is consumed locally and never replaces normal server admission. Admission creates a stable high-entropy Student class-session capability; the learner may remain **Waiting / unassigned** with no workspace edit authority until the Instructor assigns a team or individual workspace. Once assigned, the browser exchanges the class session for a fresh assignment-specific editable workspace capability, keeps that workspace capability memory-only, and attaches it to the existing collaboration engine without entering the URL. Reassignment disconnects old authority before the Student enters the destination team's existing Intake; unassign returns the Student to Waiting. Connected Students see class/workspace/identity context, public **Templates**, protected Classroom Case Studies, and read-only Instructor coaching including optional notes and **Changed since review**. On narrow screens the Class, Case, Team, and Notes secondary surfaces default compact but remain one-action accessible; those collapse states are presentation-only. Switching away pauses live classroom sync while preserving class resume; **Leave class** clears resume and restores the local Intake captured before joining.
- **Instructor** uses **Start a class**, receives one human Student join code, and can copy the code, share a fragment-only join link, or show a fully local QR for that same safe link. The Instructor sees Waiting/assigned participants, creates team or individual workspaces, and assigns/reassigns/unassigns Students through accessible selectors. The Instructor capability is retained locally for same-device resume; lost cross-device authority will be handled by the separately authorized Administration / Maintenance experience in #329 rather than a public bearer-code form. The dashboard can rapidly switch into a **live read-only** view of each Student/team Intake and provide field-level coaching. Observation uses the normal Intake renderer but server authorization keeps the Instructor credential outside Student edit capability. The same Instructor class capability authorizes protected teaching Case Studies. The Class rail defaults compact on narrow screens without changing session authority. Switching away pauses observation while preserving same-device class resume; **Leave class** clears the Instructor resume and restores the instructor's prior local Intake.
Expand Down
4 changes: 4 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ Never commit, log, paste into issues, or include in test fixtures:
- database connection strings or credentials;
- raw collaboration workspace tokens or secret links;
- Instructor class capabilities, Student class-session capabilities, or assignment-specific classroom workspace capabilities;
- the `INTAKE_ADMIN_TOKEN` Administration / Maintenance credential;
- authorization headers;
- production incident snapshots containing confidential data;
- private participant identity data.

The collaboration capability model treats possession of the correct secret as authorization. Classroom separates privileges across Instructor class authority, human admission code, Student class session, and assignment-specific Student workspace authority. Server code stores only hashes for high-entropy bearer capabilities and must not log raw capabilities or snapshots.

Administration / Maintenance is a separate privileged boundary documented in `docs/admin-maintenance.md`. `INTAKE_ADMIN_TOKEN` is environment-only, is never an Intake or Classroom credential, and is accepted only in the `Authorization` header for `/api/admin`. The browser may retain a successfully verified Admin token only in tab-scoped `sessionStorage` under `kt-admin-session-v1`; it must never enter `localStorage`, Intake persistence, files, summaries, templates, URLs, logs, analytics, or telemetry. Admin inventory never returns raw capabilities or Intake snapshots. Physical purge requires a short-lived signed server preview; changed activity/state invalidates the preview before deletion. Classroom-owned workspaces cannot be purged independently of their owning class.


Same-device Student resume stores the high-entropy **Student class-session capability** under `kt-classroom-student-session-v1` together with public class/participant/current-assignment context. The human join code is discarded after admission. The current assignment-specific workspace capability is **memory-only** and must be reacquired after reload or reassignment; it must not be written into the live resume envelope or URL. #328 intentionally rejects older pre-production Student session-envelope formats. No Student resume envelope may enter Intake state, exports, summaries, templates, analytics, logs, or error telemetry.

For same-device Instructor resume, the browser retains the Instructor class capability under `kt-classroom-instructor-session-v1` together with public class metadata, the human Student join code, and the last selected public workspace ID. This credential may administer/list/observe only its represented class through Instructor classroom APIs. It must never enter Intake state, exports, summaries, templates, URLs, analytics, logs, error telemetry, or `collaboration_workspace_capabilities`.
Expand Down
18 changes: 18 additions & 0 deletions api/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,24 @@ These rules apply to all server-only modules below `api/`.
- Responses containing capabilities or private Intake data use `Cache-Control: no-store` and `Referrer-Policy: no-referrer`.
- Display names are presentation metadata, never identity or authorization.

## Administration / Maintenance boundary

Read `docs/admin-maintenance.md` before editing `api/admin.js`, `api/_admin.js`, `INTAKE_ADMIN_TOKEN`, maintenance inventory, lifecycle recovery, or purge behavior.

Rules:

- Administration is not Standalone, Student, or Instructor authority and must never be accepted on normal Classroom/collaboration endpoints.
- `INTAKE_ADMIN_TOKEN` is environment-only and must never be stored in the database, browser localStorage, Intake state, URLs, logs, analytics, or test snapshots.
- `/api/admin` is the single deployable Admin entrypoint; do not create a directory of Admin function wrappers.
- Admin responses are always `Cache-Control: no-store` and `Referrer-Policy: no-referrer`.
- Inventory may return non-secret public maintenance IDs and lifecycle metadata, but never raw capability values/hashes or Intake snapshots.
- Instructor recovery rotates to a new capability and returns that raw value once; historical bearer credentials are not recoverable.
- Physical purge is preview-first. The signed preview must be short-lived, commit must re-read/revalidate the exact candidate plan, and a changed plan returns conflict rather than silently widening deletion.
- Recent collaboration presence is activity. Never purge an apparently idle workspace based only on old snapshot/update time when recent presence exists.
- Class-owned collaboration workspaces are physically deleted only with their owning class.
- Bulk purge SQL must guard the complete requested candidate set before mutation and preserve FK cascade integrity.
- Do not introduce autonomous scheduled deletion until a separate roadmap item explicitly approves it.

## Classroom capability boundaries

Read `docs/classroom-api.md` and `docs/classroom-architecture.md` before modifying classroom endpoints.
Expand Down
Loading
Loading