Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 9 additions & 0 deletions .agent/knowledge/data-contracts.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ Document API and data-shape assumptions that must stay compatible over time.

## Contracts

- Date: 2026-04-29
- Surface: internal module | activity interface
- Contract: Activity-owned session normalizers that return a typed `data` object must preserve the shared `controlAuthority` record whenever the activity opts into single-instructor control ownership.
- Compatibility constraints: Shared ownership helpers store authority in `session.data.controlAuthority`, but activity-local normalizers like SyncDeck's may rebuild `data` field-by-field. If they omit `controlAuthority`, ownership appears to claim successfully in one code path and then vanishes on the next normalized read or websocket update.
- Validation rules: Normalization should round-trip `{ mode, ownerInstanceId, ownerTakenAt, overrideInherited }`, defaulting through the shared control-authority normalizer rather than trusting arbitrary persisted values.
- Evidence (schema/tests/path): `server/controlAuthority.ts`; `activities/syncdeck/server/routes.ts`; `activities/syncdeck/server/routes.test.ts`
- Follow-up action: When another activity with its own `normalizeSessionData(...)` adopts control authority, audit that normalizer immediately instead of assuming shared helper writes are enough.
- Owner: Codex

- Date: 2026-04-17
- Surface: activity interface | websocket | internal module
- Contract: SyncDeck student-side instructor sync suppression must derive incoming slide indices from all Reveal state shapes that can drive a `setState`, including `payload.indices`, `payload.navigation.current`, `payload.revealState`, and top-level state fields. Same-horizontal vertical instructor moves must remain suppressible even when the deck emits `revealState` without a separate `indices` object.
Expand Down
9 changes: 9 additions & 0 deletions .agent/knowledge/security-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ Track security-relevant boundaries, risks, and mitigation decisions.

## Notes

- Date: 2026-05-08
- Area: Playwright SyncDeck instructor bootstrap
- Threat or risk: Seeding E2E manager pages by writing a real `instructorPasscode` into browser `sessionStorage` creates the same clear-text credential persistence pattern the product avoids where possible, and triggers CodeQL clear-text storage findings.
- Control or mitigation: SyncDeck manager bootstrap no longer persists instructor passcodes in browser storage, and the control-authority Playwright test now fulfills the manager passcode API from the test runner instead of injecting the secret into browser storage.
- Residual risk: The passcode still exists in test process memory and is returned to app code through the manager bootstrap API path; the mitigation removes browser storage persistence from the product and harness.
- Validation (test/review/path): `playwright/control-authority.spec.ts`
- Follow-up action: Prefer route/cookie/bootstrap shims or same-tab memory helpers over Web Storage writes when E2E tests need manager credentials.
- Owner: Codex

- Date: 2026-03-22
- Area: Playwright production-mode test secret handling
- Threat or risk: Committing a fixed `PERSISTENT_SESSION_SECRET` in the Playwright harness creates secret-scanner noise and normalizes checking pseudo-secrets into the repo, even when the value is test-only.
Expand Down
9 changes: 9 additions & 0 deletions .agent/knowledge/testing-patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ Capture reusable test setup patterns, common failure modes, and reliability guid

## Entries

- Date: 2026-04-29
- Scope: integration
- Pattern: Server-side maintenance timers created during route handling should call `unref?.()` when they are only background cleanup helpers, especially in activity route modules that schedule delayed pruning or telemetry refresh work.
- Why it helps: Real `setTimeout` handles created during focused route tests can keep the Node process alive and make a healthy suite hang with `Promise resolution is still pending but the event loop has already resolved`, even when the assertions themselves pass. `unref()` keeps production cleanup behavior while letting tests and short-lived processes exit cleanly.
- Example (file/path): `activities/video-sync/server/routes.ts`; `activities/video-sync/server/routes.test.ts`
- Failure signal: A route test file appears to pass in narrowed subsets but the full file hangs until external timeout because background timers remain referenced after the test completes.
- Follow-up action: Prefer `unref?.()` for non-critical cleanup timers, and if a test needs to inspect timer scheduling directly, patch `setTimeout` locally while still returning an object shape that tolerates optional `unref`.
- Owner: Codex

- Date: 2026-03-04
- Scope: integration
- Pattern: Session-store mocks for route tests should return deep clones from `get()` and store clones on `set()` when production storage serializes records between calls.
Expand Down
Loading