Commit Graph

21 Commits

Author SHA1 Message Date
ac0bf80eca fix(auth): port server-side session revocation and sign-in hardening
Ports the upstream auth audit fixes onto the kept auth feature:

- revoke sessions server-side via an in-memory jti denylist (B5):
  createSession embeds the session id as the JWT jti, invalidateSession
  denylists it for the max token lifetime, validateSession rejects
  denylisted and jti-less (fail-closed) tokens; constant-time signature
  comparison (B4). Adds session-denylist.ts + test.
- cover signToken/verifyToken/validateSession crypto paths without a
  running Payload by stubbing the payload module (B8).
- derive clientIp server-side from trusted proxy headers and drop it from
  the public sign-in input schema; thread it as a server-only request
  context argument so a client can no longer spoof its rate-limit bucket
  (B2).
- declare the auth-injected email (and displayName) in the users
  collection-level DSR pii map so Art. 15 export and Art. 17 soft delete
  cover them (A5). Adapted to our collection set (no username field).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 23:53:43 +02:00
8b114351a8 chore(tooling): port upstream infra/tooling audit fixes
Reconciles the upstream audit-fix PR's infra changes onto the Veect
control-plane fork (kept-file portions only; deleted demo features
skipped):

- resolve the root playwright config in pnpm test:visual (S8)
- prune dead VERCEL_ENV from turbo.json globalEnv (S9)
- drop the duplicate chromium install in the storybook CI job (S10)
- wire scripts/**/*.test.mjs under a dedicated vitest runner
  (vitest.scripts.config.mjs + pnpm test:scripts + CI validate step);
  convert node:test imports to vitest keeping node:assert; fix the
  work-tree fixtures to mirror the docs/work/epics/ layout
- ignore *.tsbuildinfo repo-wide and untrack the committed build state
- align every @trpc/* range on ^11.18.0 so the workspace resolves to a
  single version (peer-warning-free install)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 23:40:07 +02:00
eec402d49d feat(workspaces): status and list use cases
getWorkspaceStatus returns persisted { id, status } only (runner-driven
transitions arrive in story 07); listWorkspaces returns the
credential-free workspace array with a strict void input (optional on
the tRPC procedure so clients can call without args). Repository gains
listWorkspaces on interface, mock, and Payload impl; the contract suite
covers listing incl. the never-returns-credentials guarantee.
Controller span+capture wrapping is extracted into a shared
bindWorkspacesController helper used by both binders, trimming the
bind-production/bind-dev-seed clone family fallow was flagging.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 22:36:18 +02:00
c990e1b871 feat(workspaces): encrypted write-only credential storage
Workspaces Payload collection with the PAT as a write-only field:
access.read () => false strips it from every access-controlled read
path, and a field-level beforeChange hook encrypts on write with
AES-256-GCM (scrypt key from VEECT_SECRET, random per-value salt + IV,
v1 storage format) via node:crypto only. The real repository replaces
the phase-1 stub with payload create/findByID; toDomain never maps the
credential, and getDecryptedCredential(id) is the single server-side
decrypt path for the runner handoff (story 07). Contract suite now
covers create, write-only behaviour, and the decrypt path against both
the mock and the Payload impl (stub runs the real collection hooks).
Missing VEECT_SECRET fails production bind/boot with an actionable
message; dev-seed boots without it. Env declared in turbo.json
globalEnv + .env.example.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 22:36:18 +02:00
8219c1fabb feat(workspaces): connectWorkspace use case with audit
Manifest-first: connectWorkspace declared mutates:true with the
workspace-connected audit event, requiredCores gains audit. Workspace
entity gains gitUrl + persisted status enum (created/connecting/ready/
error). Input takes name + git URL + PAT; the output schema is the
credential-free workspace entity, so the PAT can never round-trip.
Audit emission asserted with RecordingAuditLog; binders wire the use
case through wireUseCase with the __audited brand, and web-next
bindAll now binds core-audit (payload+stdout sinks in production,
stdout in dev-seed) so boot conformance passes in both modes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 22:36:18 +02:00
6216897680 feat(workspaces): scaffold feature
Scaffold the workspaces feature package via pnpm turbo gen feature
(single Workspace entity, getWorkspace use case) and hand-wire the
aggregators: bindAll dispatcher (web-next), core-api app router, and
workspace deps. Release-please registration reverted per the root-only
versioning policy (AGENTS.md, ADR-027 retrofit). Pinned @trpc/server
to the repo-wide 11.16.0 resolution so instanceof TRPCError checks
share one module instance.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 22:35:55 +02:00
9495023aed feat(editor): board shell with iframe frame and selection overlay
React Flow board (pan/zoom + frame drag are pure editor-side transforms
— zero canvas-protocol traffic, <16ms budget) hosting one iframe frame
node on the adapter origin. The frame waits for runtime.ready
(queue-drain) behind an explicit 'Starting preview…' skeleton, then
requests a single Element via render-frame (core-runner-protocol
schema) plus geometry; agent-reported geometry stays frame-local and
click reports drive store selection. The selection ring renders as an
editor-side overlay from reported geometry — chrome never inside the
customer's document (ADR-028). Stories + jsdom component tests for
board/frame/overlay; Storybook stories glob extended to
packages/editor (verified via static build).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 22:18:24 +02:00
c2f56ac8c9 feat(editor): canvas-protocol client and store
The editor side of the ADR-028 canvas protocol: local .strict() zod
schemas (runtime.ready, geometry.report, click.target agent events;
render-frame reused from @repo/core-runner-protocol + geometry.request
editor commands; direction-specific envelopes) and a client that pins
targetOrigin in BOTH directions — outbound posts never use '*', inbound
drops wrong-origin, wrong-source, and schema-invalid events before any
handler runs. Shapes are deliberately small and reconcile with the
adapter's agent script in stories 05/10. Unit-tested against a scripted
agent double; zustand store holds registry + selection ONLY (DesignDoc
v1 arrives with the design-doc epic, ADR-029).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 22:07:08 +02:00
c42eca5b80 feat(editor): scaffold editor package
UI-only feature package for the ADR-029 editor rebuild: tsconfig
rootDir '.', vitest jsdom base with '@' alias and honest L0 baseline
thresholds, conformance ESLint active, React 19, @xyflow/react +
zustand wired against the pre-approved 2026-07-12 library traces.
Minimal feature.manifest.ts (empty useCases — no binders; declares
requiredCores runner-protocol + baseline coverage band) so the editor
participates in pnpm conformance without weakening any lint rule.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 22:00:34 +02:00
52f3b19dfe feat(core-runner-protocol): v0 message schemas with round-trip tests
Envelope pins protocolVersion "0" and carries the workspace-scoped
auth token; discriminated union on type covers hello/ready, clone,
install, scan, adapter-start, render-frame, status (stage + elapsed),
and error (named causes). All .strict() so the control plane, editor,
and runner cannot drift apart silently (ADR-027, PRD user story 7).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 21:47:34 +02:00
15dc6b9128 feat(core-runner-protocol): scaffold protocol package
Hand-scaffolded from the packages/core-events shape: the core-package
turbo generator only covers its eight pre-curated snapshot names
(analytics, audit, consent, dsr, events, realtime, trpc, ui) and
rejects 'runner-protocol' at the name prompt. Flagged in the package
AGENTS.md as a future generator snapshot candidate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 21:47:34 +02:00
2bd882e0b0 feat(core-testing): git-serving fixture helpers
serveFixtureRepo(fixtureDir) copies a fixture into a temp dir, commits
it as a fresh single-commit repo, bare-clones it, and serves it over
`git daemon --export-all` on an ephemeral localhost port (default) or
as a file:// URL (fallback for daemon-less environments). Returns
{ cloneUrl, bareRepoPath, protocol, stop } with idempotent teardown.
Tests exercise a real `git clone` of fixtures/vite-kitchen over both
protocols. New subpath export @repo/core-testing/git — node-only, so
deliberately not on the jsdom root barrel. No new runtime deps: node
built-ins + system git (present in git's exec-path on macOS and the
ubuntu CI image).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 21:40:52 +02:00
46250c819f docs(agents): rewrite package map and conventions for Veect
AGENTS.md now describes the Veect control plane (ADR-027/028/029,
docs/product/ authority table, glossary Veect-domain vocabulary), with
the package map, boundary tags, and per-package conventions verified
against the filesystem (auth + 11 core + 3 tooling packages;
web-next/cms/storybook apps) and code examples drawn from the real auth
feature. Adds warning notes for known generator staleness — the
release-please per-feature registration that would collide with the
root-only v* tag policy, the pre-shipped trace overwrite hazard (zod
incident, restored in e4a3b65), the trpc template's removed
@trpc/react-query dep — and records the accepted warn-severity lint
backlog (~93 findings).

Per story amendments, the same slice prunes the dead "web-tanstack"
member from core-shared's app-tag unions (bind-otel-instrumentation.ts,
sentry/init-client.ts; tests retargeted to "web-next") and fixes the
stale app/feature tag lists in docs/architecture/overview.md. A warning
comment mirrors the release-please note at the generator call site; no
functional generator changes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 21:06:38 +02:00
e50306cbf6 feat(core-realtime): scaffold realtime optional core
Generator-emitted scaffold (pnpm turbo gen core-package realtime) plus
the story-00-precedent coverage repairs (coverage provider devDep,
symbols.ts exclude + tested allowlist mirror) and three minimal tests
covering generator-emitted realtime code the template suite misses.
Squash of 31d85e0 + review-fix cf11b38.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 20:35:09 +02:00
fc13424e9d feat(core-events): scaffold events optional core
Scaffolded via pnpm turbo gen core-package events (generator-first,
ADR-022 pre-shipped zod trace landed in docs/library-decisions/).
Generator wired transpilePackages + E1/J eslint rule block. Two
story-00-precedent additions so the coverage gates pass: the
@vitest/coverage-v8 devDep (L0 sweep) and the honest symbols.ts
exclude (mirroring core-shared/vitest.config.ts) plus its missing
ALLOWED_GLOBS mirror in scripts/coverage/diff.mjs (L1 gate). No
consumers wired — compile-green floor for the walking-skeleton
PRD (ADR-027).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 20:35:09 +02:00
48bf4da4cd refactor(navigation)!: delete navigation demo feature
Veect retrofit (ADR-027): fifth and final slice of the demo-content
removal. Deletes packages/navigation whole and prunes every composition
edge in one commit: core-api router mount + dep + router test, core-cms
header-global composition + dep + regenerated Payload types (globals
now empty), web-next bindAll (prod + dev-seed) + tests + Tailwind
source + transpilePackages + dep, cms/core-cms payload config test
assertions, home e2e nav assertion, tsconfig paths, fallow
ignoreDependencies entry, anchor-guard FEATURES list, generator e2e
strip lists + reference-feature comments (navigation -> auth, incl.
feature templates + scaffolding guide), lockfile prune, and
feature-list doc trims (CLAUDE.md, AGENTS.md, glossary, app/feature
AGENTS.md). Compliance YAML regeneration produced no churn (navigation
declared no PII).

Cycle break: navigation's UI hooks were the last edge closing the
committed core-trpc -> core-api -> navigation -> core-trpc package
cycle. With it gone, the lint turbo task graph builds for the first
time and every package's ESLint executes; the epic's lint waiver
expires here. Latent findings: 3 errors, all mechanical, fixed
in-slice - require() import in turbo/generators/config.ts
(no-require-imports), literal type assertion in auth's
authentication.service.ts (prefer-as-const), and next-env.d.ts
triple-slash in apps/cms (rule scoped off for that generated file,
mirroring web-next's existing override). 99 warn-severity findings
remain across 5 packages (pii-declaration-must-be-complete on test
fixtures, turbo/no-undeclared-env-vars on test env keys) - all
warn-by-design, non-gating.

core-trpc keeps a consumer (apps/web-next providers) and stays per
ADR-027. Its unused @trpc/react-query dependency, surfaced by the
post-deletion fallow audit, is removed rather than ignore-listed -
core-trpc's hooks use @trpc/tanstack-react-query. Remaining fallow
warn (auth validateSession "unused member") is a false positive: the
method implements IAuthenticationService and is exercised in
container.test.ts; auth stays untouched as the regression canary.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 19:34:54 +02:00
9ee941863d refactor(marketing-pages)!: delete marketing-pages demo feature
Veect retrofit (ADR-027): fourth slice of the demo-content removal.
Deletes packages/marketing-pages whole and prunes every composition
edge in one commit: core-api router mount + dep, core-cms
collection/global composition + dep + regenerated Payload types,
web-next bindAll (prod + dev-seed) + tests + about page + Tailwind
source + transpilePackages + dep, cms/core-cms payload config test
assertions, marketing-page e2e spec, tsconfig paths, fallow ignore
entry, anchor-guard + generator e2e feature lists, compliance
data-map + retention-policy regeneration, lockfile prune, and
feature-list doc entries (CLAUDE.md, AGENTS.md, glossary, app/feature
AGENTS.md).

Event teardown: marketing-pages was the sole consumer of
auth.user.signed-up (welcome-email handler + job). The handler, its
Payload tasks, and the bus subscription all lived inside the package's
own binders, so they die with it — no other package wires the
subscription. Auth's manifest `publishes` stays untouched: a publisher
with zero consumers is legal (pnpm conformance only fails on orphan
consumers, verified green). The app-level sign-up-welcome-email test
asserted the marketing-pages mailer stays empty without a bus; it is
deleted with the feature, and the now-unused test-only bind-state
helpers in web-next bind-production.ts go with it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 17:23:08 +02:00
80beacfe88 refactor(media)!: delete media demo feature
Veect retrofit (ADR-027): third slice of the demo-content removal.
Deletes packages/media whole and prunes every composition edge in one
commit: core-api router mount + dep, core-cms collection composition +
dep + regenerated Payload types, web-next bindAll (prod + dev-seed) +
tests + Tailwind source + transpilePackages + dep, cms/core-cms/web-next
payload config test assertions, tsconfig paths, anchor-guard + generator
e2e feature lists, compliance data-map + retention-policy regeneration,
lockfile prune, and feature-list doc entries (CLAUDE.md, AGENTS.md,
glossary, app/feature AGENTS.md).

Media was the uploads feature: the marketing-pages pages.hero.image and
navigation header.logo upload fields (relationTo: "media") are removed
from those collections in this slice — Payload config sanitization
rejects a relationship to a missing collection. Both features' domain
entities keep their optional imageId/logoId fields; their repositories
already tolerate the fields being absent. Both features are deleted in
later slices.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 16:26:42 +02:00
ea24c85424 refactor(blog)!: delete blog demo feature
Veect retrofit (ADR-027): the template's demo content is being removed
to make room for the Veect package map. This slice deletes
packages/blog whole and prunes every composition edge in one commit:
core-api router mount, core-cms collections + regenerated Payload
types, web-next bindAll entry / home page / blog route / Tailwind
sources, blog e2e spec, tsconfig paths, fallow ignore entry,
anchor-guard + generator e2e feature lists, compliance artifacts,
and feature-list doc entries (CLAUDE.md, AGENTS.md, glossary).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 15:56:22 +02:00
093de02711 fix(tooling): restore L0 coverage sweep across all packages
The template baseline shipped 9 packages without @vitest/coverage-v8
and documented an L0 invocation turbo cannot parse — the full coverage
sweep had never run. Adds the provider (pinned to the feature-package
spec), a root test:coverage script, corrects every live doc/prompt/CI
occurrence, and calibrates coverage excludes for the 4 packages whose
latent threshold failures the outage masked (framework glue only —
zero threshold numbers changed). L0 sweep now passes 21/21.

Squash of a284baa + 5c6af95 (worktree-agent-a013c67cea83b2636),
implemented and reviewed via the dispatch loop under the epic's
baseline waiver (lint pending story 03).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
2026-07-12 13:55:00 +02:00
fraqtal
ee0fec0691 Initial commit 2026-07-12 08:15:46 +00:00