{
  "markdown": "# circulara-core\n\nCirculara Observe tier: per-tenant backend + MCP plugin. Sprints 1-4: WS0 (scaffold),\nWS6 (pricing registry), WS1 (MCP plugin), WS2 (auth + BYO keys + gateway), WS3\n(telemetry pipeline: normalize -> re-price -> append; free-tier cap; OpenAI-format\ngateway for Cursor-class hosts), WS4 (meter compute: registry pricing, energy/CO2e\nranges with confidence labels, per user/team/module/month report), WS5 (Observe\ndashboard + savings-potential report + monthly statement, server-rendered, Ledger\nLight brand tokens; seed a demo tenant with packages/backend/scripts/seed-demo.ts\nand open the printed /dashboard URL).\nArchitecture: /outputs/reports/architecture_v1.md (AD1-AD6, rev 2026-07-07) + the\nsourcing addendum (AD7-AD12).\n\n**Pricing placement:** the meter owns money. All three capture paths (hook, tool,\ngateway) deliver tokens + model; pricing happens ONCE in the WS3/WS4 pipeline from the\napproved registry snapshot. Client-submitted observe events are re-priced server-side;\nclient cost is a hint, never the booked number. Engine-computed events (reuse/sourcing,\nwaves 3+) carry their own math and are born meter-priced in-process.\n\n## Workspace layout\n\n| Package | What |\n|---|---|\n| packages/schema | THE event schema (zod, v1.0+v1.1, AD4/AD12 incl. call_id + M1 stacking rule). Single source of truth for backend intake AND plugin emission |\n| packages/backend | Per-tenant backend: tenancy/isolation (PGlite+pgvector dev, per-tenant Postgres prod), append-only meter, seats (AD6), WS2 auth (OIDC + short-lived agent tokens + dev mode), BYO provider keys envelope-encrypted at rest, gateway metering mode (AD3-B, M2 per-seat credentials), object store, WS6 pricing registry + carbon coefficients |\n| packages/plugin | MCP plugin (AD3 path C tools: circulara_report, circulara_status) + Claude Code PostToolUse hook (path A observe capture). Validates events against the shared schema BEFORE sending |\n\n## Run\n\n```bash\nnpm install\nnpm test              # all workspaces: backend 11 + plugin 4 (in-memory, no keys)\nnpm run typecheck\nnpm run dev           # backend on 127.0.0.1:8787 (CIRCULARA_AUTH_MODE=dev|oidc)\n\n# WS6 registry flow (human approves diffs, D12):\nnpm run registry -- update|approve|show\n\n# WS2 LIVE smoke (deliberate; ~cents on the configured Anthropic key):\ncd packages/backend && npx tsx scripts/live-smoke.ts\n```\n\n## Auth (WS2)\n\n- Humans: OIDC/SSO (RS256 vs org issuer JWKS; admin via `circulara_role=admin` claim).\n- Named agents: short-lived HS256 seat tokens minted at POST /v1/seats/:id/token (admin).\n- Dev mode ONLY with CIRCULARA_AUTH_MODE=dev: `Bearer dev-admin-token` / `dev-seat-token`.\n- Gateway (M2): per-seat credentials from POST /v1/seats/:id/gateway-credential; the host\n  sends the credential as x-api-key to POST /gateway/anthropic/v1/messages; backend maps\n  credential -> seat, forwards on the tenant's real key, meters per seat.\n\n## MCP plugin install (Claude Code)\n\n```bash\nclaude mcp add circulara \\\n  -e CIRCULARA_BACKEND_URL=http://127.0.0.1:8787 \\\n  -e CIRCULARA_TENANT_ID=<uuid> -e CIRCULARA_TOKEN=<bearer> \\\n  -e CIRCULARA_SEAT_ID=<uuid> -e CIRCULARA_USER_ID=<sso-subject> \\\n  -- npx tsx <repo>/packages/plugin/src/server.ts\n```\nHook capture (path A): wire `packages/plugin/src/hook.ts` as a PostToolUse hook (see file\nheader). The hook never fails the host tool call.\n\n## Invariants the tests enforce\n\n- Tenant isolation; append-only meter_events; admin-only agent seats (AD6).\n- avoided_usd == counterfactual - actual; sourcing types require the v1.1 block; M1\n  call_id chaining telescopes per-call savings.\n- Provider keys never at rest in plaintext (envelope AES-256-GCM, wrong-KEK/tamper throw);\n  write-only API (names listed, values never returned).\n- Gateway: unknown credential 401; missing tenant key 503; per-seat attribution exact;\n  registry-priced usage.\n- OIDC: wrong issuer rejected; dev tokens rejected outside dev mode; agent tokens expire.\n\n## Keys\n\nRuntime keys come ONLY from the external env file via loadSecret() (path in\nsrc/config.ts, names in /context/api.md): CIRCULARA_MASTER_KEY (envelope KEK),\nCIRCULARA_AGENT_TOKEN_SECRET (agent JWTs), tenant provider keys via the API.\nNever hardcoded, never logged, never committed.\n",
  "bytes": 4224,
  "sha": "e6c25fcb5f61e7976cec8165285e3033709629af7b5c2e770d6a03c0a828a265",
  "repo_slug": "circularroute/circulara-core",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_ai_circulara_plugin_2b45e3ab/readme"
}