From d0a1492f6c9489a79429ac10a1ab05379f1a1643 Mon Sep 17 00:00:00 2001 From: Tyler Gillispie Date: Tue, 25 Aug 2026 12:08:59 -0700 Subject: [PATCH] docs(tasks): establish tasks/do.md execution protocol and link from path.md --- tasks/do.md | 49 ++++++++ ...c.auth-api.zero-trust-scope-guards-1805.md | 89 ++++++++++---- ...rch.monolith-decomposition-roadmap-1845.md | 111 +++++++++++++----- ....story.ui.redesign-sessions-drawer-1812.md | 57 ++++++--- tasks/path.md | 16 +-- 5 files changed, 251 insertions(+), 71 deletions(-) create mode 100644 tasks/do.md diff --git a/tasks/do.md b/tasks/do.md new file mode 100644 index 0000000..c798b64 --- /dev/null +++ b/tasks/do.md @@ -0,0 +1,49 @@ +# Task Implementation Execution Protocol (`tasks/do.md`) + +This protocol defines the standard for executing an approved task from +`tasks/new/`. + +--- + +## 1. Direct Execution Protocol (When You Are Doing the Task) + +When commanded to **"tasks/do `[TASK_FILE]`"**: + +1. **Move to WIP:** Move the task file from `tasks/new/` to `tasks/wip/` before + starting work. +2. **Follow the 4-Step State Machine:** + - **Step 1 (Research):** Inspect the target files and verify architectural + assumptions. + - **Step 2 (Implementation):** Apply minimal, pure functional modifications. + Preserve existing docstrings and comments. + - **Step 3 (Quality Gates):** Run all verification gates: + - `deno fmt` + - `deno task lint` + - `deno task check` + - `deno test --allow-all` (Run ONLY hermetic unit tests; NEVER run + `deno task start` in container sandboxes). + - **Step 4 (Review & Move):** Upon all gates passing, move the task file to + `tasks/complete/YYYY-MMDD.XX.agent.type.scope.title-HHMM.md`. +3. **Commit & Sync:** Commit with standard conventional commit syntax and push + to both remotes (`origin` and `gitea`). + +--- + +## 2. Dispatch Template (When Preparing a Prompt for Jules or External Agents) + +When commanded to **"tasks/do a prompt for Jules on `[TASK_FILE]`"**, fill in +and provide the following block: + +```text +**Role:** Act as an Implementation Engineer. + +**The Task:** Please review and execute the approved task plan in `[tasks/new/TASK_FILENAME.md]`. + +**Directives:** +1. Follow the strict 4-step state machine (Research -> Implementation -> Quality Gates -> Review). +2. Move the task file from `tasks/new/` to `tasks/wip/` before starting, and to `tasks/complete/` upon verification. +3. Apply minimal, pure functional modifications adhering to `AGENTS.md`. +4. Run all quality gates: `deno fmt`, `deno task lint`, `deno task check`, and `deno test --allow-all`. +5. Run ONLY unit tests (`deno test --allow-all`). Do NOT run `deno task start` or `deno task dev` (database daemons are not running in container sandboxes). +6. Provide a concise summary of all modified files and verified test results upon completion. +``` diff --git a/tasks/new/2026-0825.01.jul.sec.auth-api.zero-trust-scope-guards-1805.md b/tasks/new/2026-0825.01.jul.sec.auth-api.zero-trust-scope-guards-1805.md index cc1c90d..f73343e 100644 --- a/tasks/new/2026-0825.01.jul.sec.auth-api.zero-trust-scope-guards-1805.md +++ b/tasks/new/2026-0825.01.jul.sec.auth-api.zero-trust-scope-guards-1805.md @@ -1,40 +1,76 @@ # TASK METADATA -- **Target Files:** `server/auth-session.ts`, `server/routes/sessions.ts`, `server/routes/events.ts`, `server/main.ts`, `ui/mod.ts`, `server/main.test.ts` -- **Core Objective:** Implement strict Zero-Trust scope enforcement and permission guards across all Auth-Yes internal API routes and SSR UI pages to ensure delegated and read-only sessions cannot escalate privileges, perform unauthorized mutations, or access admin interfaces. +- **Target Files:** `server/auth-session.ts`, `server/routes/sessions.ts`, + `server/routes/events.ts`, `server/main.ts`, `ui/mod.ts`, + `server/main.test.ts` +- **Core Objective:** Implement strict Zero-Trust scope enforcement and + permission guards across all Auth-Yes internal API routes and SSR UI pages to + ensure delegated and read-only sessions cannot escalate privileges, perform + unauthorized mutations, or access admin interfaces. - **Dependencies:** None -- **Additional Important Notes:** Delegated sessions (`is_agent = true`) must hold strictly the intersection of user permissions and assigned `custom_scopes`. Self-revocation of a delegated session is permitted, but revoking other sessions is prohibited without `write:sessions` or `*`. +- **Additional Important Notes:** Delegated sessions (`is_agent = true`) must + hold strictly the intersection of user permissions and assigned + `custom_scopes`. Self-revocation of a delegated session is permitted, but + revoking other sessions is prohibited without `write:sessions` or `*`. --- ## Architectural Considerations & Risks - **Risks:** - - **Backward-Compatibility with Cached Sessions:** Existing delegated sessions in the Valkey cache might lack explicit scopes if they were created before this strict enforcement. The middleware must default to a safe deny state for unknown or missing scopes but handle legacy `is_agent = true` sessions gracefully by denying mutating actions unless explicitly permitted. - - **Self-Revocation Edge Case:** The guard logic must correctly distinguish between a session revoking itself (which is always allowed for clean logouts) and a session attempting to revoke a sibling or parent session. - - **Global Admin Resolution:** The `isGlobalAdmin` check relies on database queries or cache. Ensure that the new middleware does not introduce significant latency by repeatedly querying PostgreSQL on every protected route. Use Valkey caching where possible. + - **Backward-Compatibility with Cached Sessions:** Existing delegated sessions + in the Valkey cache might lack explicit scopes if they were created before + this strict enforcement. The middleware must default to a safe deny state + for unknown or missing scopes but handle legacy `is_agent = true` sessions + gracefully by denying mutating actions unless explicitly permitted. + - **Self-Revocation Edge Case:** The guard logic must correctly distinguish + between a session revoking itself (which is always allowed for clean + logouts) and a session attempting to revoke a sibling or parent session. + - **Global Admin Resolution:** The `isGlobalAdmin` check relies on database + queries or cache. Ensure that the new middleware does not introduce + significant latency by repeatedly querying PostgreSQL on every protected + route. Use Valkey caching where possible. - **Alternatives:** - - Instead of injecting `customScopes` into the Valkey cache session payload, we could perform a database lookup on every privileged API request to determine exact grants. However, this violates the Auth-Yes architectural principle of fast-path caching at the edge and would significantly degrade performance. The chosen approach of checking scopes from the cached `AuthenticatedUser` object is highly modular and performant. + - Instead of injecting `customScopes` into the Valkey cache session payload, + we could perform a database lookup on every privileged API request to + determine exact grants. However, this violates the Auth-Yes architectural + principle of fast-path caching at the edge and would significantly degrade + performance. The chosen approach of checking scopes from the cached + `AuthenticatedUser` object is highly modular and performant. ## Proposed Implementation ### 1. Scope Guard Helpers (`server/auth-session.ts`) -Implement reusable composable functions to evaluate the current user's capabilities. -- `hasScope(auth: AuthenticatedUser, requiredScope: string): boolean`: Evaluates if `auth.customScopes` contains `*` or the `requiredScope`. If `!auth.isAgent`, returns `true` (primary sessions have all capabilities). + +Implement reusable composable functions to evaluate the current user's +capabilities. + +- `hasScope(auth: AuthenticatedUser, requiredScope: string): boolean`: Evaluates + if `auth.customScopes` contains `*` or the `requiredScope`. If + `!auth.isAgent`, returns `true` (primary sessions have all capabilities). - Create Hono middleware helpers: - - `requirePrimarySession()`: Denies access with `403 Forbidden` if `auth.isAgent === true`. - - `requireScope(scope: string)`: Denies access if `hasScope(auth, scope)` returns false. - - `requireAdmin(auth: AuthenticatedUser)`: Uses `isGlobalAdmin(auth.userId)` and verifies `!auth.isAgent` OR `auth.customScopes.includes("*")`. + - `requirePrimarySession()`: Denies access with `403 Forbidden` if + `auth.isAgent === true`. + - `requireScope(scope: string)`: Denies access if `hasScope(auth, scope)` + returns false. + - `requireAdmin(auth: AuthenticatedUser)`: Uses `isGlobalAdmin(auth.userId)` + and verifies `!auth.isAgent` OR `auth.customScopes.includes("*")`. ### 2. Guard Internal API Routes + Apply the newly created guards to critical endpoints. - **`server/routes/sessions.ts`** - - `DELETE /api/sessions/:id`: Allow if target `id === auth.sessionId`. Otherwise, require `write:sessions` scope. - - `PUT /api/sessions/:id/scopes`: Require `admin` or `*` scope, OR `write:sessions`. + - `DELETE /api/sessions/:id`: Allow if target `id === auth.sessionId`. + Otherwise, require `write:sessions` scope. + - `PUT /api/sessions/:id/scopes`: Require `admin` or `*` scope, OR + `write:sessions`. - `POST /api/sessions/:id/extend`: Require `write:sessions` or `*`. - - `POST /api/sessions/delegate`: Prevent privilege escalation. Require `admin` or `*` scope to delegate an `admin` mode session. If creating a `read_only` or `operator` session, require the delegator to have at least those equivalent scopes. + - `POST /api/sessions/delegate`: Prevent privilege escalation. Require `admin` + or `*` scope to delegate an `admin` mode session. If creating a `read_only` + or `operator` session, require the delegator to have at least those + equivalent scopes. - **`server/routes/events.ts`** - `POST /api/events`: Require `write:events` or `*`. @@ -42,15 +78,26 @@ Apply the newly created guards to critical endpoints. - `POST /api/events/:id/extend`: Require `write:events` or `*`. - **`server/main.ts`** - - Apply `requirePrimarySession()` or `requireAdmin()` to `/api/admin/*` and `/api/passkeys/*` endpoints. + - Apply `requirePrimarySession()` or `requireAdmin()` to `/api/admin/*` and + `/api/passkeys/*` endpoints. ### 3. SSR UI Gates (`ui/mod.ts`) + Guard the user interfaces against unauthorized delegated sessions. -- `/admin/*`: Verify `isAdmin && (!auth.isAgent || auth.customScopes.includes("*"))`. Redirect unauthorized sessions to `/dashboard` or return a `403 Forbidden` page. -- `/dashboard/passkeys`: Verify `!auth.isAgent`. Delegated sessions cannot manage passkeys. + +- `/admin/*`: Verify + `isAdmin && (!auth.isAgent || auth.customScopes.includes("*"))`. Redirect + unauthorized sessions to `/dashboard` or return a `403 Forbidden` page. +- `/dashboard/passkeys`: Verify `!auth.isAgent`. Delegated sessions cannot + manage passkeys. ### 4. Testing (`server/main.test.ts`) + - Write tests that create a delegated session with only `read_only` scopes. -- Assert that this session gets a `403 Forbidden` when attempting to call `POST /api/sessions/delegate`, `DELETE /api/sessions/:other_id`, and `POST /api/events`. -- Assert that the delegated session can successfully call `DELETE /api/sessions/:own_id`. -- Write tests verifying that a delegated session attempting to access `/admin/users` is redirected/blocked. \ No newline at end of file +- Assert that this session gets a `403 Forbidden` when attempting to call + `POST /api/sessions/delegate`, `DELETE /api/sessions/:other_id`, and + `POST /api/events`. +- Assert that the delegated session can successfully call + `DELETE /api/sessions/:own_id`. +- Write tests verifying that a delegated session attempting to access + `/admin/users` is redirected/blocked. diff --git a/tasks/new/2026-0825.01.jul.story.arch.monolith-decomposition-roadmap-1845.md b/tasks/new/2026-0825.01.jul.story.arch.monolith-decomposition-roadmap-1845.md index e369a45..120d3e3 100644 --- a/tasks/new/2026-0825.01.jul.story.arch.monolith-decomposition-roadmap-1845.md +++ b/tasks/new/2026-0825.01.jul.story.arch.monolith-decomposition-roadmap-1845.md @@ -1,73 +1,126 @@ # TASK METADATA -- **Target Files:** `server/main.ts`, `server/main.test.ts`, `ui/components/SessionsPage.tsx`, `server/auth-session.ts`, `ui/mod.ts`, `infra/setup.ts`, `ui/utils/bip39_wordlist.ts` (and copies), `spire_ffi/Cargo.lock`, `ui/components/AdminInvitesPage.tsx`, `ui/components/AdminUserDetailsPage.tsx`, `deno.lock`, `ui/components/AdminRolesPage.tsx`, `ui/components/AdminAppsPage.tsx` -- **Core Objective:** Architect a phased, zero-regression modular decomposition plan to eliminate monoliths and enforce the Single Responsibility Principle. +- **Target Files:** `server/main.ts`, `server/main.test.ts`, + `ui/components/SessionsPage.tsx`, `server/auth-session.ts`, `ui/mod.ts`, + `infra/setup.ts`, `ui/utils/bip39_wordlist.ts` (and copies), + `spire_ffi/Cargo.lock`, `ui/components/AdminInvitesPage.tsx`, + `ui/components/AdminUserDetailsPage.tsx`, `deno.lock`, + `ui/components/AdminRolesPage.tsx`, `ui/components/AdminAppsPage.tsx` +- **Core Objective:** Architect a phased, zero-regression modular decomposition + plan to eliminate monoliths and enforce the Single Responsibility Principle. - **Dependencies:** None. -- **Additional Important Notes:** Must preserve zero-dependency SDK purity (`@auth-yes/sdk`) and guarantee 100% backward compatibility with all quality gates (`deno fmt`, `deno task lint`, `deno task check`, `deno task test`). +- **Additional Important Notes:** Must preserve zero-dependency SDK purity + (`@auth-yes/sdk`) and guarantee 100% backward compatibility with all quality + gates (`deno fmt`, `deno task lint`, `deno task check`, `deno task test`). --- ### 2. Architectural Considerations & Risks - **Risks:** - - **Circular Dependencies:** Moving components could introduce circular dependencies, especially between `auth-session.ts` and routing files. - - **Regression:** Splitting monolithic files (e.g., `main.test.ts`) might cause tests to fail or miss edge cases if not carefully separated by domain tier. - - **Client-Side Breakage:** Extracting inline JS strings from JSX (e.g., `SessionsPage.tsx`) to external vanilla JS files could break dynamic interactions if DOM elements are not correctly targeted or if loading sequence is altered. + - **Circular Dependencies:** Moving components could introduce circular + dependencies, especially between `auth-session.ts` and routing files. + - **Regression:** Splitting monolithic files (e.g., `main.test.ts`) might + cause tests to fail or miss edge cases if not carefully separated by domain + tier. + - **Client-Side Breakage:** Extracting inline JS strings from JSX (e.g., + `SessionsPage.tsx`) to external vanilla JS files could break dynamic + interactions if DOM elements are not correctly targeted or if loading + sequence is altered. - **Alternatives:** - - Instead of extracting completely to static files, use Deno Island architectures if supported, but given the strict instruction to use pure Hono SSR JSX (strictly no React) and vanilla JavaScript, static ES modules under `ui/public/ui/` or `ui/static/` is the optimal, native approach. + - Instead of extracting completely to static files, use Deno Island + architectures if supported, but given the strict instruction to use pure + Hono SSR JSX (strictly no React) and vanilla JavaScript, static ES modules + under `ui/public/ui/` or `ui/static/` is the optimal, native approach. ### 3. Proposed Implementation -The refactoring will be executed in a safe, phased approach to guarantee zero regressions: +The refactoring will be executed in a safe, phased approach to guarantee zero +regressions: #### Phase 1: UI Sessions Decomposition (Frontend) + - **Target:** `ui/components/SessionsPage.tsx` - **Actions:** - - Extract the Event Cockpit Deck logic into `ui/components/sessions/EventCockpitDeck.tsx`. - - Extract the Workshop Launch Drawer logic into `ui/components/sessions/WorkshopDrawer.tsx`. - - Extract the 1:1 Delegation Drawer logic into `ui/components/sessions/DirectPassDrawer.tsx`. + - Extract the Event Cockpit Deck logic into + `ui/components/sessions/EventCockpitDeck.tsx`. + - Extract the Workshop Launch Drawer logic into + `ui/components/sessions/WorkshopDrawer.tsx`. + - Extract the 1:1 Delegation Drawer logic into + `ui/components/sessions/DirectPassDrawer.tsx`. - Extract the Scope Modal logic into `ui/components/sessions/ScopeModal.tsx`. - - Move the 400+ lines of raw client-side JavaScript currently embedded in string templates (`dangerouslySetInnerHTML`) into a dedicated static vanilla JS module (e.g., `ui/public/ui/sessions.js`) and link it via a `