spec: add v2-secure-session-core shape spec
All checks were successful
All checks were successful
Phase 1 of SPEC-002 (GuruConnect v2). Keystone-first plan: Tasks 1-4 rebuild the auth/session core that closes the 3 audit CRITICALs by design (per-agent cak_ keys, plane separation, session-scoped viewer tokens, blacklist+frame-caps+throttle on the relay WS, single-use rate-limited support codes, tenancy-ready schema); Tasks 5-7 deliver attended consent, native full key fidelity (WH_KEYBOARD_LL hook, scan-code injection, SAS Ctrl+Alt+Del), and HW H.264 with raw+Zstd fallback. plan/shape/references/ standards. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
171
specs/v2-secure-session-core/plan.md
Normal file
171
specs/v2-secure-session-core/plan.md
Normal file
@@ -0,0 +1,171 @@
|
||||
# v2 Secure Session Core — Implementation Plan
|
||||
|
||||
> Spec created: 2026-05-29
|
||||
> Status: not started
|
||||
> Parent: `docs/specs/SPEC-002-v2-modernization-architecture.md` (Phase 1)
|
||||
> Keystone: Tasks 1–4 are the "get-right-first" secure auth/session core — every audit CRITICAL/HIGH
|
||||
> is closed there. Tasks 5–7 deliver the product capability on top. Do them in order.
|
||||
|
||||
## Task 0: Commit this spec
|
||||
|
||||
Commit the `specs/v2-secure-session-core/` directory before writing any code:
|
||||
|
||||
```
|
||||
git add specs/v2-secure-session-core/
|
||||
git commit -m "spec: add v2-secure-session-core shape spec"
|
||||
```
|
||||
|
||||
Do not start Task 1 until this commit exists.
|
||||
|
||||
---
|
||||
|
||||
## Task 1 (KEYSTONE): v2 schema — per-agent keys + tenancy-ready tables
|
||||
|
||||
Files touched: `server/migrations/` (new v2 migration files), `server/src/db/` (rebuilt modules:
|
||||
`agent_keys.rs` [new], `sessions.rs`, `machines.rs`, `support_codes.rs`, `events.rs`, `users.rs`,
|
||||
`mod.rs`).
|
||||
|
||||
- New table `connect_agent_keys`: `id UUID`, `machine_id UUID FK`, `key_hash TEXT`, `tenant_id UUID NULL`,
|
||||
`created_at`, `last_used_at`, `revoked_at TIMESTAMPTZ NULL`. Keys are `cak_`-prefixed, stored hashed
|
||||
(SHA-256, mirroring v1's hash helper); plaintext returned once at issuance.
|
||||
- Add nullable `tenant_id UUID` to `machines`, `sessions`, `support_codes`, `events`, `users`,
|
||||
`connect_agent_keys`, defaulting to a single bootstrap tenant row. Add a `tenants` table with one seed row.
|
||||
- `sessions` gains `is_managed BOOLEAN`, `source TEXT` (`'standalone'|'gururmm'`), `consent_state TEXT`
|
||||
(`'not_required'|'pending'|'granted'|'denied'`), `tenant_id`.
|
||||
- `support_codes`: add single-use semantics — `consumed_at TIMESTAMPTZ NULL`; widen the code column to
|
||||
hold a higher-entropy human-readable code (see Task 4).
|
||||
- Migrations are **idempotent** (`CREATE TABLE IF NOT EXISTS` / `ADD COLUMN IF NOT EXISTS`), applied on
|
||||
server startup, recorded in `_sqlx_migrations`. New queries use runtime `sqlx::query()`.
|
||||
- DB modules expose a `tenancy` helper that today resolves every call to the default tenant (Phase-4
|
||||
switch point). Struct fields match columns (the v1 audit flagged 3 unmapped v003 columns — don't repeat).
|
||||
|
||||
Reference: `specs/native-remote-control/plan.md` Task 2 (`connect_agent_keys`); `.claude/standards/gururmm/sqlx-migrations.md`.
|
||||
|
||||
---
|
||||
|
||||
## Task 2 (KEYSTONE): Rebuilt auth model — plane separation + session-scoped viewer tokens
|
||||
|
||||
Files touched: `server/src/auth/` (`mod.rs`, `jwt.rs`, `agent_keys.rs` [new], `token_blacklist.rs`,
|
||||
`password.rs`), `server/src/api/auth.rs`, `server/src/api/sessions.rs`.
|
||||
|
||||
- **Delete the JWT-as-agent-key path.** Remove the `jwt_config.validate_token` branch from
|
||||
`validate_agent_api_key` (`relay/mod.rs:224`); agent authentication validates a `cak_` per-agent key
|
||||
(hash compare against `connect_agent_keys`, reject if `revoked_at` set) OR a support code — **never a
|
||||
user JWT**.
|
||||
- **Session-scoped viewer tokens:** new endpoint `POST /api/sessions/:id/viewer-token` (auth: dashboard
|
||||
JWT + authorization that the user may view that session/machine) mints a short-lived (~5 min) JWT whose
|
||||
claims include `session_id` and `tenant_id`. This replaces "any dashboard JWT can view any session."
|
||||
- Keep Argon2id passwords; keep the blacklist but make `is_revoked()` callable from the WS layer (Task 3).
|
||||
- Per-agent key issuance endpoint (admin): `POST /api/machines/:id/keys` → returns plaintext `cak_` once,
|
||||
stores hash. `DELETE /api/machines/:id/keys/:key_id` sets `revoked_at`.
|
||||
|
||||
Reference: `relay/mod.rs:224` (`validate_agent_api_key` — the CRITICAL), `auth/mod.rs:116`
|
||||
(blacklist already consulted for REST — extend to WS), `specs/native-remote-control/plan.md` Tasks 2/3/6;
|
||||
`.claude/standards/security/credential-handling.md`, `.claude/standards/api/response-format.md`.
|
||||
|
||||
---
|
||||
|
||||
## Task 3 (KEYSTONE): Secure relay WS handlers + bounded relay
|
||||
|
||||
Files touched: `server/src/relay/mod.rs`, `server/src/session/mod.rs`.
|
||||
|
||||
- **`viewer_ws_handler`** (`relay/mod.rs:242`): verify the viewer token's **signature + expiry +
|
||||
blacklist + `session_id` claim == requested `session_id`** before `handle_viewer_connection`
|
||||
(`relay/mod.rs:595`). Reject otherwise. (Fixes the any-JWT-joins-any-session + blacklist-bypass CRITICALs.)
|
||||
- **`agent_ws_handler`** (`relay/mod.rs:55`): authenticate via per-agent key OR support code only
|
||||
(Task 2). Persistent reattach must bind to the authenticated machine identity, not a query-string
|
||||
`agent_id` alone (`session/mod.rs:98`).
|
||||
- **Frame caps:** set explicit `.max_message_size(...)`/`.max_frame_size(...)` on both
|
||||
`WebSocketUpgrade`s; reject oversized frames before `to_vec()`/broadcast. (Fixes WS-OOM HIGH.)
|
||||
- **Input throttle:** bound + rate-limit the viewer→agent input queue (`relay/mod.rs:669`); cap events/sec.
|
||||
- Reconcile managed sessions from DB on startup so they aren't orphaned.
|
||||
|
||||
Reference: audit Pass E (`reports/2026-05-29-gc-audit.md` §"Pass 5"); `relay/mod.rs:242,55,595,669`.
|
||||
|
||||
---
|
||||
|
||||
## Task 4 (KEYSTONE): Working rate limiting + single-use support codes
|
||||
|
||||
Files touched: `server/src/middleware/rate_limit.rs` (rebuild — v1 is non-compiling),
|
||||
`server/src/middleware/mod.rs`, `server/src/api/auth.rs` (login), `server/src/api/` (code validate),
|
||||
`server/src/db/support_codes.rs`, `server/src/relay/mod.rs` (code bind).
|
||||
|
||||
- Rebuild a **compiling** rate-limit layer (fix the `tower_governor` generics, or a small in-memory
|
||||
fixed-window limiter); re-enable `pub mod rate_limit`. Wire it to `POST /api/auth/login`,
|
||||
`POST /api/auth/change-password`, and the support-code validate route.
|
||||
- **Single-use codes:** consume atomically on first agent bind (accept only a `pending`, unconsumed code;
|
||||
set `consumed_at`); reject a second presenter. (Fixes the reusable-code HIGH.)
|
||||
- **Widen the code:** higher-entropy human-readable format (e.g. grouped base32, ~40+ bits) replacing
|
||||
6-digit numeric; add per-IP lockout on repeated validate failures.
|
||||
|
||||
Reference: audit Pass B/E (rate limiting disabled/non-compiling; reusable codes); `middleware/mod.rs:3-11`.
|
||||
|
||||
---
|
||||
|
||||
## Task 5: Attended-mode consent
|
||||
|
||||
Files touched: `proto/guruconnect.proto`, `agent/src/session/mod.rs`, `agent/src/` (consent UI dialog),
|
||||
`server/src/relay/mod.rs`, `server/src/session/mod.rs`.
|
||||
|
||||
- Add `ConsentRequest` / `ConsentResponse` to the proto (after `AdminCommand`).
|
||||
- On an attended session, the agent shows a consent dialog to the end user; the server keeps the session
|
||||
`consent_state = pending` and surfaces it to the technician only on `granted`. `denied`/timeout → tear down.
|
||||
- Managed/unattended sessions follow per-tenant policy (default: silent for managed; `consent_state =
|
||||
not_required`). Audit the consent decision to `events`.
|
||||
|
||||
Reference: `specs/native-remote-control/plan.md` Task 5 (Consent primitive); proto `AdminCommand` insertion point.
|
||||
|
||||
---
|
||||
|
||||
## Task 6: Native viewer — full key fidelity
|
||||
|
||||
Files touched: `agent/src/viewer/` (low-level hook + input capture), `agent/src/input/keyboard.rs`
|
||||
(extend — salvaged), `agent/src/input/mod.rs`, `agent/src/bin/sas_service.rs` (wire — salvaged),
|
||||
`proto/guruconnect.proto` (confirm `KeyEvent`/`SpecialKeyEvent` coverage).
|
||||
|
||||
- **Viewer capture:** install `WH_KEYBOARD_LL` while the viewer is in focused control; divert system
|
||||
combos (Win key, Win+R, Alt+Tab, Ctrl+Esc) and forward as `KeyEvent` (VK + scan code + extended flag)
|
||||
instead of letting the local shell act. Add a "send system keys to remote" toggle.
|
||||
- **Agent injection:** scan-code `SendInput` (`KEYEVENTF_SCANCODE` + correct `KEYEVENTF_EXTENDEDKEY` for
|
||||
right-Ctrl/Alt, arrows, Win, Insert/Home). Extend the salvaged `input/keyboard.rs`.
|
||||
- **Ctrl+Alt+Del:** `SpecialKeyEvent.CTRL_ALT_DEL` → the salvaged SAS service (`bin/sas_service.rs`,
|
||||
`SendSAS`, SYSTEM, `SoftwareSASGeneration` policy set by the managed installer).
|
||||
- **Modifier hygiene:** track modifier up/down; **re-sync (release) on focus loss** to kill stuck modifiers.
|
||||
|
||||
Reference: SPEC-002 §4.1/§4.2; salvage ledger §2; `agent/src/input/keyboard.rs`, `agent/src/bin/sas_service.rs`.
|
||||
|
||||
---
|
||||
|
||||
## Task 7: Hardware H.264 encode + negotiated raw/Zstd fallback
|
||||
|
||||
Files touched: `agent/src/encoder/` (`mod.rs`, `h264.rs` [new], `raw.rs` [salvaged]),
|
||||
`agent/src/capture/` (feed), `agent/src/viewer/` (decode), `proto/guruconnect.proto`
|
||||
(`AgentStatus` capability, `SessionResponse` codec), `server/src/session/mod.rs` (negotiation).
|
||||
|
||||
- HW **H.264** via Windows Media Foundation (transparently NVENC/AMF/QuickSync) emitting the proto's
|
||||
`EncodedFrame` (h264). Native viewer decodes via MF/D3D11.
|
||||
- **Fallback:** salvaged raw BGRA + Zstd + dirty-rects for Win7 / no HW encoder.
|
||||
- **Negotiation:** agent advertises HW-encode capability in `AgentStatus`; server selects the codec in
|
||||
`SessionResponse`; default H.264, HEVC opt-in, raw fallback. One encode feeds the native viewer now
|
||||
(and the Phase-2 WebRTC track later).
|
||||
|
||||
Reference: SPEC-002 §5; `agent/src/encoder/raw.rs` (salvaged), `proto/guruconnect.proto` (EncodedFrame already modeled).
|
||||
|
||||
---
|
||||
|
||||
## Task 8: Verification (end-to-end, observable)
|
||||
|
||||
- **Security (re-audit clean):** run `/gc-audit --pass=security` (and `--pass=rust`) → the three relay
|
||||
CRITICALs and the rate-limiting/frame-cap/reusable-code HIGHs are gone. Manually confirm: a revoked
|
||||
`cak_` key is rejected on `/ws/agent`; a viewer token for session A is rejected on session B; a
|
||||
logged-out (blacklisted) viewer token is rejected on `/ws/viewer`; a user JWT is rejected as an agent key.
|
||||
- **Attended flow:** generate a support code → run the one-time agent → end user sees + accepts consent →
|
||||
technician's session appears only after acceptance; a denied consent tears down.
|
||||
- **Key fidelity (the headline):** in a live session, confirm **Win+R opens Run on the remote**, **Ctrl+C
|
||||
on remote / Ctrl+V locally** (and vice-versa, text), and **Ctrl+Alt+Del reaches the remote secure
|
||||
desktop**. Confirm no stuck modifiers after alt-tabbing away and back.
|
||||
- **Codec:** confirm a HW-H.264 machine negotiates h264 (check `SessionResponse`), a Win7/no-HW machine
|
||||
falls back to raw+Zstd, both render correctly in the native viewer.
|
||||
- **Rate limiting:** hammer `/api/auth/login` and the code-validate route → confirm throttling/lockout.
|
||||
- **Migrations:** fresh DB applies the v2 migrations cleanly; `_sqlx_migrations` consistent; `tenant_id`
|
||||
populated with the default tenant.
|
||||
59
specs/v2-secure-session-core/references.md
Normal file
59
specs/v2-secure-session-core/references.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# v2 Secure Session Core — Code References
|
||||
|
||||
All paths relative to `projects/msp-tools/guru-connect/`. Line numbers are from the v1 tree as of the
|
||||
2026-05-29 audit; treat them as anchors, re-grep before editing.
|
||||
|
||||
## Files that will be REBUILT (v1 broken/unsafe — see audit)
|
||||
|
||||
- `server/src/relay/mod.rs` — the relay. `agent_ws_handler:55`, `validate_agent_api_key:224` (the
|
||||
JWT-as-agent-key CRITICAL — delete the JWT branch), `viewer_ws_handler:242` (no per-session authz, no
|
||||
blacklist check — the two other CRITICALs), `handle_viewer_connection:595`, input forward `:669` (no
|
||||
throttle). No WS frame-size caps anywhere. **Rebuild auth + add caps + throttle (Tasks 2–4).**
|
||||
- `server/src/middleware/rate_limit.rs` + `middleware/mod.rs:3-11` — rate limiting commented out and
|
||||
non-compiling. **Rebuild + wire (Task 4).**
|
||||
- `server/src/db/support_codes.rs` — codes accepted in `pending` OR `connected` state (reusable); 6-digit
|
||||
numeric. **Add single-use consume + widen (Task 4).**
|
||||
- `server/src/db/{sessions,machines,events,users}.rs`, `server/src/db/mod.rs` — flat, no `tenant_id`, no
|
||||
agent-key table. **Rebuild with tenancy-ready schema + `agent_keys.rs` (Task 1).**
|
||||
- `server/src/session/mod.rs` — persistent reattach keyed on query-string `agent_id:98` (no crypto proof).
|
||||
**Bind to authenticated identity; reconcile on startup (Task 3).**
|
||||
- `server/src/auth/{mod,jwt,token_blacklist,password}.rs` — keep Argon2id + exp enforcement; **add
|
||||
per-agent-key validation + session-scoped viewer-token minting; expose blacklist to the WS layer (Task 2).**
|
||||
- `server/migrations/00{1,2,3}_*.sql` — v1 schema. **New v2 migrations layer on top (Task 1).**
|
||||
|
||||
## Files that will be SALVAGED (proven — extend, don't rewrite)
|
||||
|
||||
- `agent/src/capture/{dxgi,gdi,display,mod}.rs` — screen capture (DXGI primary, GDI fallback, multi-display).
|
||||
Feed the encoder (Task 7).
|
||||
- `agent/src/input/{keyboard,mouse,mod}.rs` — input injection. **Extend `keyboard.rs` for scan-code +
|
||||
extended-key fidelity (Task 6).**
|
||||
- `agent/src/bin/sas_service.rs` — the privileged Ctrl+Alt+Del (SendSAS) helper. **Wire to
|
||||
`SpecialKeyEvent.CTRL_ALT_DEL` (Task 6).**
|
||||
- `agent/src/encoder/{mod,raw}.rs` — raw BGRA + Zstd path. **Keep as the fallback; add `h264.rs` (Task 7).**
|
||||
- `agent/src/transport/{mod,websocket.rs}` — prost-over-WSS codec (audit-confirmed correct). Reuse;
|
||||
rebuild only the auth handshake.
|
||||
- `proto/guruconnect.proto` — well-modeled. **Extend: `ConsentRequest`/`ConsentResponse` (Task 5),
|
||||
`AgentStatus` codec capability + `SessionResponse` codec (Task 7); `KeyEvent`/`SpecialKeyEvent` already
|
||||
cover full fidelity.**
|
||||
- `server/static/viewer.html:196-489` — the *correct* protobuf parser (reference; not used in Phase 1's
|
||||
native path).
|
||||
|
||||
## Similar existing implementations to follow
|
||||
|
||||
- **Per-agent hashed keys + issuance + session pre-create + viewer tokens + consent:**
|
||||
`specs/native-remote-control/plan.md` Tasks 2/3/5/6 — the prior shape-spec that already designed these
|
||||
for the RMM-integration case. Phase 1 makes them the *core* model, not integration-only.
|
||||
- **Blacklist already consulted for REST:** `server/src/auth/mod.rs:116` — replicate this check on the WS
|
||||
paths (the gap that caused the viewer-WS blacklist-bypass CRITICAL).
|
||||
- **Framing allowlist pattern:** `server/src/middleware/security_headers.rs:30` (`frame-ancestors 'none'`)
|
||||
— untouched in Phase 1; the per-route allowlist is Phase 3.
|
||||
- **GuruRMM enrollment (`agk_` keys, `POST /api/enroll`, hashed storage):** `projects/msp-tools/guru-rmm/
|
||||
server/src/api/enroll.rs` + `db/enroll.rs` — the Option-3 pattern GC's `cak_` keys mirror.
|
||||
|
||||
## Database schema
|
||||
|
||||
v1 tables (`connect_machines`, `connect_sessions`, `connect_session_events`, `connect_support_codes`,
|
||||
`users`, `user_permissions`, `user_client_access`, `releases`) carry over with **new nullable `tenant_id`
|
||||
columns + a seed `tenants` table + new `connect_agent_keys` table** (Task 1). UUID PKs, `TIMESTAMPTZ`,
|
||||
soft-delete preference, FK `ON DELETE CASCADE` (GC + RMM convention). Idempotent migrations, runtime
|
||||
`sqlx::query()`, applied on startup — see `.claude/standards/gururmm/sqlx-migrations.md`.
|
||||
75
specs/v2-secure-session-core/shape.md
Normal file
75
specs/v2-secure-session-core/shape.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# v2 Secure Session Core — Shape & Constraints
|
||||
|
||||
> Spec created: 2026-05-29
|
||||
> Parent: [`docs/specs/SPEC-002-v2-modernization-architecture.md`](../../docs/specs/SPEC-002-v2-modernization-architecture.md) → Phase 1
|
||||
> Audit being fixed: [`reports/2026-05-29-gc-audit.md`](../../reports/2026-05-29-gc-audit.md)
|
||||
|
||||
## What this is
|
||||
|
||||
The foundation phase of the GuruConnect v2 rebuild: a rebuilt auth + session model that makes the
|
||||
three audit CRITICALs structurally impossible, plus the native viewer delivering full keyboard
|
||||
fidelity (Win+R, Ctrl+C/V, Ctrl+Alt+Del) and a hardware H.264 video path with a raw+Zstd fallback.
|
||||
A technician can run a secure attended (consent-gated) or unattended (per-agent-key) session with
|
||||
full control, end to end, with zero relay-plane auth holes.
|
||||
|
||||
## What this is NOT (out of scope — deferred to later v2 phases)
|
||||
|
||||
- **File transfer** (clipboard cut/paste + drag-and-drop) — SPEC-002 §4.4, **Phase 2**. Clipboard
|
||||
*text/image* sync may land here; file `CF_HDROP` transfer does not.
|
||||
- **Web / WebRTC viewer** — **Phase 2**. Phase 1 is the native viewer only.
|
||||
- **The dashboard** (machines/sessions/codes/releases UI) — **Phase 2**. Phase 1 exposes the REST/WS
|
||||
surface and the native viewer; the web dashboard is rebuilt next.
|
||||
- **The `/api/integration/v1/` RMM contract** + embedded viewer + programmatic session pre-create —
|
||||
**Phase 3**.
|
||||
- **Multi-tenancy activation** (partner→client isolation, dev impersonation, SSO) — **Phase 4**. Phase 1
|
||||
ships the tenancy-*ready* schema (nullable `tenant_id`, default tenant) but does NOT enforce isolation.
|
||||
- **Session recording, BACKSTAGE mode, multi-monitor switching, quality-preset UI** — deferred.
|
||||
- **Drag-out (remote→local) file transfer** — Phase 2+ (the hard `IDataObject` case).
|
||||
- **macOS/Linux agents** — Windows-first remains.
|
||||
|
||||
## Hard constraints
|
||||
|
||||
- **Native-first, custom protobuf-over-WSS.** No WebRTC in this phase. Full key fidelity is the reason
|
||||
(browsers can't deliver Win key / Ctrl+Alt+Del).
|
||||
- **No TOML/config files for endpoints** (RMM rule): relay URL compiled into the agent; identity baked
|
||||
at generation or in the registry; server secrets via env/SOPS only. Never an `agent.toml`.
|
||||
- **Salvage, don't rewrite, the proven cores** (SPEC-002 §2): DXGI/GDI capture, input injection, the
|
||||
SAS helper, the prost codec, the proto, the Gitea-Actions CI all carry over.
|
||||
- **Single statically-linked Windows agent** (no .NET/VC++ redist); Win7 SP1+ target → raw+Zstd codec
|
||||
fallback is mandatory for machines without a HW H.264 encoder.
|
||||
- **Rust/Axum server, PostgreSQL + sqlx**; new queries use runtime `sqlx::query()`; idempotent
|
||||
migrations applied on server startup.
|
||||
- **No new standing credential granted to any party** — viewer tokens are short-lived and
|
||||
session-scoped; agent keys are per-agent and revocable.
|
||||
- **Clean wholesale cutover** — no v1 data migration; v2 replaces v1 at connect.azcomputerguru.com once
|
||||
this phase is live.
|
||||
|
||||
## Key decisions (from SPEC-002, locked 2026-05-29)
|
||||
|
||||
- **Per-agent hashed keys** (`connect_agent_keys`, `cak_…`) replace the shared `AGENT_API_KEY` (RMM
|
||||
Option 3). Shared key remains only as a deprecated fallback.
|
||||
- **Plane separation:** agent auth = per-agent key OR support code; viewer auth = JWT. The
|
||||
`validate_agent_api_key` JWT-accepting branch (`relay/mod.rs:224`) is **deleted**.
|
||||
- **Session-scoped viewer tokens:** a viewer JWT is minted (~5 min TTL) only by an authenticated +
|
||||
authorized request for a specific session; the WS verifies signature + expiry + blacklist + that the
|
||||
token's session claim matches the requested `session_id`.
|
||||
- **Single-use support codes:** atomic consume on first agent bind; widened entropy (human-readable,
|
||||
not 6-digit numeric); rate-limit + lockout on the validate endpoint.
|
||||
- **Bounded relay:** explicit `max_message_size`/`max_frame_size` on both WS upgrades; bounded +
|
||||
rate-limited input queue.
|
||||
- **Attended consent:** new proto `ConsentRequest`/`ConsentResponse`; the technician sees the session
|
||||
only after the end user accepts on their machine.
|
||||
- **Tenancy-ready, not tenant-yet:** nullable `tenant_id` on all scoped tables, default tenant; a
|
||||
tenancy helper resolves to the default now and flips to enforcement in Phase 4 — no schema rewrite.
|
||||
- **Codec:** H.264 default (Media Foundation, HW-accelerated), HEVC opt-in, raw+Zstd fallback,
|
||||
negotiated per session via `AgentStatus` capability + `SessionResponse`.
|
||||
|
||||
## Priority
|
||||
|
||||
P1 — foundational; blocks all later v2 phases and fixes the live-production security CRITICALs.
|
||||
|
||||
## Roadmap reference
|
||||
|
||||
- [`docs/specs/SPEC-002-v2-modernization-architecture.md`](../../docs/specs/SPEC-002-v2-modernization-architecture.md) §6 Phase 1, §3 (architecture), §8 (security map).
|
||||
- [`docs/FEATURE_ROADMAP.md`](../../docs/FEATURE_ROADMAP.md) → "Server/API" (the false `[x]` rate-limiting split), "Security & Infrastructure", and the GuruRMM-Integration "Per-machine agent keys" item.
|
||||
- Prior shape-spec art: [`specs/native-remote-control/`](../native-remote-control/) (per-agent keys, session pre-create, viewer tokens, consent — Tasks 2/3/5/6 there).
|
||||
58
specs/v2-secure-session-core/standards.md
Normal file
58
specs/v2-secure-session-core/standards.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# v2 Secure Session Core — Applicable Standards
|
||||
|
||||
The following standards from `.claude/standards/` apply to this feature.
|
||||
|
||||
## security/credential-handling
|
||||
|
||||
No hardcoded credentials — JWT secret and the integration/agent keys come from env/SOPS only.
|
||||
Argon2id for passwords (keep). **Per-agent keys and viewer tokens are hashed at rest and short-lived;
|
||||
log every auth attempt (success and failure).** Directly governs Tasks 2–4 (the whole point of the phase).
|
||||
|
||||
Source: `.claude/standards/security/credential-handling.md`
|
||||
|
||||
## api/response-format
|
||||
|
||||
RESTful plural nouns, kebab-case multi-word segments (`/viewer-token`), a consistent error envelope
|
||||
(`{ detail, error_code, status_code }` — and do NOT leak raw `e.to_string()`, the audit's Pass B finding),
|
||||
pagination where lists grow, **idempotent sqlx migrations**. Governs the new endpoints in Tasks 2/4.
|
||||
|
||||
Source: `.claude/standards/api/response-format.md`
|
||||
|
||||
## gururmm/sqlx-migrations
|
||||
|
||||
Never manually pre-apply migrations; use `CREATE TABLE IF NOT EXISTS` / `ADD COLUMN IF NOT EXISTS`; let
|
||||
the server apply its own migrations on startup and record them in `_sqlx_migrations`. Governs Task 1
|
||||
(the v2 schema). (GC is PostgreSQL like RMM, so RMM's checksum/INET lessons transfer.)
|
||||
|
||||
Source: `.claude/standards/gururmm/sqlx-migrations.md`
|
||||
|
||||
## gururmm/platform-parity
|
||||
|
||||
Agent features must not silently no-op on a platform — a no-op without a `// TODO(platform): <os>` stub is
|
||||
a bug. GC's agent is Windows-first, so this mostly governs the **raw+Zstd codec fallback** (Task 7 — the
|
||||
Win7/no-HW path must work, not silently produce nothing) and any server code that branches on OS.
|
||||
|
||||
Source: `.claude/standards/gururmm/platform-parity.md`
|
||||
|
||||
## conventions/naming
|
||||
|
||||
Rust `snake_case` functions/vars, `PascalCase` types; **protobuf `PascalCase` messages / `snake_case`
|
||||
fields**; database `snake_case` tables/columns. Governs the new proto messages (Task 5/7), the
|
||||
`connect_agent_keys` schema (Task 1), and all new Rust.
|
||||
|
||||
Source: `.claude/standards/conventions/naming.md`
|
||||
|
||||
## conventions/no-emojis
|
||||
|
||||
Never use emojis in code, comments, logs, commit messages, or output — ASCII markers only
|
||||
(`[OK]`/`[ERROR]`/`[WARNING]`/`[INFO]`). Applies to everything written this phase.
|
||||
|
||||
Source: `.claude/standards/conventions/no-emojis.md`
|
||||
|
||||
## git/commit-style
|
||||
|
||||
Conventional commit types (`feat:`/`fix:`/`docs:`/`refactor:`), `Co-Authored-By` trailer on Claude
|
||||
commits, never commit secrets or build artifacts. Governs Task 0 and every task commit. (Conventional
|
||||
commits also drive GC's auto-versioning per SPEC-001 §3.)
|
||||
|
||||
Source: `.claude/standards/git/commit-style.md`
|
||||
Reference in New Issue
Block a user