Files
coreci-chat/.ciagent/STATE.md
T
CIAgent 85dce28ca3 docs(PDLC): lock M3 spec v1.2 Final — Chat, Orchestration, Hardening
15 REQs (028-037, 041-045) with REQ-035 amendment (auto-promote at step 21).
3 personas (Devon/Sam/Casey), 5 journeys + J-infra, no orphan REQs.
Decisions #1-#10 locked; OQ1-6 resolved, OQ7 open (control_state write-through).
Migrations 0004-0006 (chat/workflow/posture), per-table for rollback isolation.
STATE.md updated: M3 spec locked, implementation pending.

---ci---
phase: 3
stage: spec-lock
milestone: v0.2-M3
spec: .ciagent/steer-m3-spec.md
spec_version: v1.2
status: ready-for-handoff
reqs: [028,029,030,031,032,033,034,035,036,037,041,042,043,044,045]
req035_amended: true
invariants: [INV-1,INV-2,INV-3,INV-4,INV-5,INV-6,INV-7,INV-8]
release: none
2026-08-25 12:41:16 +00:00

12 KiB

Project State Intake Format — PDLC Phase 0

1. Header (mandatory)

Project: coreci-chat Initiative: CoreCI Chat v0.1 — M3 (Chat, Orchestration, Hardening) spec locked v1.2; M1+M2 shipped, M3 spec ready for engineering handoff Initiator: ciagent (autonomous, full autonomy) Date (UTC): 2026-08-25T11:00:00Z (updated post-M3 spec lock v1.2) Current Version: v0.1.6 (M2 milestone release complete; M3 spec v1.2 Final locked, not yet implemented) System Health: GREEN — M1 complete (v0.0.1-v0.0.7, 17 REQs, 189 tests), M2 complete (v0.1.0-v0.1.6, 13 REQs, 656 tests), MCP 2025-06-18 conformance verified; M3 spec v1.2 Final ready for engineering handoff Raw Idea (≤ 3 sentences): M1 (read-only diagnostic MVP foundation) shipped: SSO, BYOM, Relay Agent, dashboard, audit, RLS, secrets. M2 (MCP Layer & Day 1 Adapters) shipped: MCP capability broker gateway, 4 adapters (Proxmox, SSH/Linux, GitHub, Gitea), SSE streaming, rate limiting, LLM smoke, CI pipeline (Gitea Actions). Desired outcome: M3 (Chat, Orchestration, Hardening, REQ-028..037+041..045) to complete v0.1 — spec locked v1.2, implementation pending.

2. Architecture State

Active Layers (which exist and are stable): [x] Core Primitives — packages/db (Postgres schema, RLS, withTenant, audit hash-chain, audit event types widened for M2), packages/secrets (SecretProvider: AWS SM + local-encrypted), packages/config (two-tier credential taxonomy), packages/runtime (Trigger.dev bootstrap + health task) [x] Domain Modules — packages/auth (WorkOS SSO, sessions, RBAC, provisioning, invitations), packages/byom (endpoint registry, validator, OpenAI-compatible routing shim, REQ-009 reject) [x] MCP Layer (M2) — packages/mcp (broker: closed 9-tool registry, adapter router, write-blocklist INV-7, token-bucket rate limiter, SSE stream manager, OpenAI↔MCP translator, in-process + stdio transports), packages/mcp/src/adapters/{proxmox,ssh,github,gitea,github-mock}, packages/llm-mock (CI-only) [x] API/Dev Surface — apps/control-plane (Next.js App Router: M1 routes + M2 routes /api/mcp/{tools,invoke,stream/[id],adapter,adapter/[id]}) [x] UI/Agent Surface — apps/control-plane/dashboard (M1: login, onboarding, targets, team, audit; M2: Settings→Adapters, Test-Call UI with SSE); apps/relay-agent (Go binary: WebSocket client, heartbeat, SSH whitelist hook + M2 tool_call handler)

Compute Topology (per environment): local: abstract — PGlite (WASM Postgres in Node), LocalEncryptedProvider, mock WorkOS, no AWS/external deps dev: N/A — same as local (PGlite + local-encrypted); no dev cluster deployed staging: UNKNOWN — needs investigation (no staging environment provisioned) prod: single-region AWS us-east-1 (target architecture: Postgres 16, AWS Secrets Manager KMS, Trigger.dev cloud, WorkOS SSO); NOT yet deployed — M1+M2 shipped code only, no prod deployment dr: N/A — single-region MVP, no DR

Identity Stack in Force: auth: WorkOS SSO/SAML (dev/mock mode in test; prod requires WORKOS_API_KEY + WORKOS_CLIENT_ID) token-vend: HS256 JWT (hand-rolled via node:crypto) for sessions + relay registration tokens; no STS signing: HS256 with SESSION_SIGNING_KEY + RELAY_TOKEN_SIGNING_KEY (env vars, tier (a) infra creds) session: httpOnly cookie + server-side sessions table row (Postgres, not tenant-scoped)

Audit Stream: source of truth: Postgres audit_log table (append-only, per-tenant hash-chain sha256(prev_hash||canonical(payload)), REVOKE UPDATE/DELETE, BEFORE INSERT trigger) event types: M1 (prompt, tool_call, ssh_command, response, config, auth, provision, validation) + M2 (adapter.configured, adapter.test_connection.{succeeded,failed}, adapter.capability_invoked, adapter.write_rejected) in-repo fallback: yes (PGlite in dev/test — same schema, RLS not enforced on SELECT in PGlite 0.5.7, app-layer withTenant + explicit WHERE is primary enforcement) retention policy: 90 days minimum, 1 year target (spec §5)

3. Technical Stack (concrete, not aspirational)

Language(s) and runtime(s): TypeScript 5.6 (Node 24.15, Next.js 15 App Router), Go 1.23.4 (static binary, CGO_ENABLED=0) Build / packaging: pnpm 11.23 workspaces (TS monorepo), go build (static ELF amd64+arm64), Gitea releases with binary + install.sh + sha256sums CI / CD: Gitea Actions (.gitea/workflows/ci.yml) — two jobs: test-pglite (default) + test-postgres (Postgres 16 service container + RLS verification). Defined in M2; requires operator to enable Gitea Actions runner + set GITHUB_SMOKE_PAT for optional Track B smoke. Infrastructure: Target: AWS us-east-1 (Postgres 16, Secrets Manager KMS). Current: local/dev only (PGlite, local-encrypted secrets). No cloud infra provisioned. Data stores: Postgres 16 (prod target) / PGlite 0.5.7 (dev/test, WASM). Tables: tenants, users, tenant_memberships, targets, byom_endpoints, invitations, audit_log (append-only hash-chain), runtime_health, sessions, mcp_adapters (M2, tenant-scoped + RLS). Secrets / KMS: Prod: AWS Secrets Manager (KMS-backed). Dev: LocalEncryptedProvider (AES-256-GCM, PBKDF2-SHA512 100k). Rotation: not implemented. External integrations in scope:

  • WorkOS — SSO/SAML + SCIM + invitation API (auth, tenant provisioning) — M1
  • Trigger.dev — async durable execution runtime (bootstrapped M1, tasks M3)
  • AWS Secrets Manager — tenant credential storage (prod)
  • Gitea (self-hosted, git.cloudinit.dev) — git forge + release distribution + CI (Gitea Actions)
  • Proxmox VE 7.x/8.x — M2 MCP adapter (PVEAuditor, read-only GET)
  • SSH/Linux (Ubuntu 24.04, Debian 12+) — M2 MCP adapter via Relay Agent (defense-in-depth whitelist)
  • GitHub — M2 MCP adapter (fine-grained PAT, metadata:read + actions:read per D-006)
  • Gitea (customer self-hosted) — M2 MCP adapter (version-aware scope validation per R-005)
  • Vanta — GRC evidence collection (M3, not yet implemented)

4. Active Constraints (the load-bearing ones)

Locked Decisions:

  • D-001: OpenAI-compatible BYOM contract (/v1/chat/completions) for M1, pluggable LlmProvider for M3
  • D-002: Relay Agent in Go (single static binary)
  • D-003: AWS Secrets Manager (prod) + local-encrypted (dev) behind SecretProvider interface
  • D-004: Postgres append-only + hash-chain audit for M1, S3 Object Lock WORM in M3
  • D-005: Next.js App Router + TypeScript single SPA
  • D-006: GitHub fine-grained PAT minimum scopes = metadata:read + actions:read (no contents:read)
  • D-007: In-process custom MCP transport for TS adapters; SSH downstream WebSocket to M1 Relay Agent
  • Spec §7 Q1-Q8: Trigger.dev, WorkOS, Vanta, install script (curl|bash) + apt fallback, fixed SSH whitelist, PVEAuditor, Gitea SaaS-to-API, pgvector (v1.1)
  • M2 spec §7 Q1-Q9: MCP 2025-06-18, 9-tool closed set, 6-command SSH subset, in-memory rate limiting, GitHub fine-grained PAT, Gitea version-aware, per-call SSE + ULID, packages/llm-mock, M2→M3 contract freeze Active Invariants:
  • INV-1: Every HTTP request hits API gateway first: auth → tenant resolve → RBAC → audit
  • INV-2: Every DB query runs under SET app.tenant_id via withTenant transaction; RLS enforces scoping
  • INV-3: Every credential resolved via SecretProvider.get; never env/config/DB for tenant secrets
  • INV-4: Every auditable event appended to audit_log with hash-chain; UPDATE/DELETE REVOKE'd; write failure halts
  • INV-5: Every LLM inference call routed to tenant's BYOM endpoint; unconfigured/unreachable → reject (REQ-009)
  • INV-6: Relay Agent outbound-only WebSocket; no inbound firewall rules on customer hosts
  • INV-7: Read-only by default — closed 9-tool registry is the primary boundary; write-method blocklist is the backstop (G-015). 100% of write-action requests rejected at broker (M2) and Relay Agent (SSH whitelist)
  • INV-8: PGlite 0.5.7 doesn't enforce RLS on SELECT — app-layer withTenant + explicit WHERE is primary in dev/test; RLS + FORCE RLS is prod backstop (verified against real Postgres 16 in CI per G-022) Standing Capability Gate: GATE-M2 — Verified (M2 acceptance gate passed: 13/13 REQs PASS, 656 tests, 15/15 gate items, MCP conformance verified, LLM smoke Track A passes, M1 non-regression) Anti-Goals Touched: Spec §2.2 out-of-scope (write actions, hosted LLM, K8s/ArgoCD/Helm, Slack/CLI/mobile, approval-gated remediation, RAG, SOC 2 cert, custom RBAC, BYOK, multi-region, Windows) Out-of-Scope (hard): Write actions (v1.1), hosted LLM inference (never), Kubernetes/ArgoCD/Helm (not planned), Slack/Teams/CLI/mobile (v1.1+), approval-gated remediation (v1.1), RAG (v1.1), SOC 2 final cert (post-MVP), custom RBAC roles (v1.2+), BYOK (v1.2+), multi-region (MVP single-region), Windows (not planned v1.x), fine-tuning (not planned)

5. Recent History & Quality Gates (last 1-2 milestones)

Last Shipped: v0.2 M2 — 2026-08-25, 7 phases (P0 pre-execution → P5 Wave J SSE+smoke+UI → P6 final review+ship), 13 REQs (015-027), 656 tests, shipped to Gitea v0.1.0-v0.1.6 + releases #833-#839 In Progress: M3 spec v1.2 Final locked (2026-08-25) — 15 REQs (028-037, 041-045), ready for engineering handoff. Implementation not started. Sub-phases M3.a (chat inline), M3.b (orchestration+durability), M3.c (hardening+metering). Coverage Floor: 92.3% (packages/mcp, the M2 critical-path package; gate ≥80% per spec §6). packages/db 98.2%, packages/llm-mock 97%. Recent Incidents: none Known Tensions:

  • PGlite RLS gap: dev/test relies on app-layer withTenant + explicit WHERE; prod RLS is the backstop. M2 CI (Gitea Actions test-postgres job) now verifies RLS against real Postgres 16 (G-022), but the Gitea Actions runner must be enabled by the operator.
  • Gitea Actions CI not yet executed: the workflow file (.gitea/workflows/ci.yml) is defined and committed, but the Gitea Actions runner has not been enabled on the forge. The P0 gate (LLM smoke Track A mock-path) does not depend on external services.
  • GITHUB_SMOKE_PAT not set: the optional Track B real-GitHub LLM smoke requires a GitHub PAT stored as a Gitea Actions secret. Track A (mock-path) is the P0 gate and needs no PAT.
  • No prod deployment: M1+M2 shipped code only; no cloud infrastructure provisioned.
  • PVEAuditor introspection gap (R-002): PVE has no clean "what role does this token have" endpoint. Broker validates "token works for reads," not "token lacks writes." Write-method blocklist is the load-bearing boundary. Documented in UI help text.
  • GitHub fine-grained PAT scope introspection gap (R-004): no public API to list a fine-grained PAT's granted scopes. Broker validates at submit + per-invocation 403. Documented in UI.

6. Agent Context & Assumptions (Agent Initiators Only)

Missing Context:

  • Gitea Actions runner status — workflow defined but runner not enabled
  • GITHUB_SMOKE_PAT — not set (optional Track B smoke)
  • Staging/prod deployment state — no cloud infra provisioned
  • WorkOS production keys — not available in this environment (dev/mock mode only)
  • AWS Secrets Manager — not available in this environment (local-encrypted fallback only)
  • Real Postgres 16 — not available locally (PGlite only); CI test-postgres job verifies RLS when runner enabled Agent Assumptions:
  • PGlite is a sufficient dev/test substitute for Postgres 16 (RLS limitation documented, CI backstops)
  • The M2 acceptance gate can be verified via unit/integration tests + LLM smoke Track A without a prod deployment
  • Gitea releases fulfill the "distribution packages" requirement
  • The next PDLC cycle is M3 (Chat, Orchestration, Hardening, REQ-028..037, REQ-041..045) — spec v1.2 Final locked

7. Canonical State References (Version/Hash)

Vision/Strategy doc: CoreCI Chat Vision v1.0 (referenced by spec, not in repo) Architecture document: .ciagent/ARCHITECTURE.md @ commit 0c15d3d (M2 milestone merge to main) Last approved SPECs: .ciagent/steer-v0.1-spec.md v1.1 (M1, locked 2026-08-24) + .ciagent/steer-m2-spec.md v1.0 (M2, locked 2026-08-25) + .ciagent/steer-m3-spec.md v1.2 (M3, locked 2026-08-25) Decision log: .ciagent/CLARIFY.md (D-001..D-007) + .ciagent/GRILL.md M1 (G-001..G-010) + M2 (G-011..G-022) + M3 spec §Key Decisions #1..#10 (no new D-* IDs; REQ-035 amendment + Decisions #7-#10 baked into steer-m3-spec.md) Invariants catalog: .ciagent/ARCHITECTURE.md §Architecture invariants (INV-1..INV-8) + M2 addition; M3 preserves all as written (session-batched Merkle is additive, not INV-4 amendment) Review artifacts: .ciagent/M1-REVIEW.md + .ciagent/M2-REVIEW.md + .ciagent/M2-VERIFY-P01.md