Skip to content

feat: add authenticated verification goal imports (#187) - #329

Merged
Joncallim merged 1 commit into
mainfrom
codex/issue-187-registry-import-api
Aug 14, 2026
Merged

feat: add authenticated verification goal imports (#187)#329
Joncallim merged 1 commit into
mainfrom
codex/issue-187-registry-import-api

Conversation

@Joncallim

@Joncallim Joncallim commented Aug 14, 2026

Copy link
Copy Markdown
Owner

Source issue

Part of #187
Parent Epic: #184
Follows #328

Why this is next

PR #328 added the repository-backed verification-goal registry and immutable snapshot storage, but the importer had no production callsite. Epic #184 orders #187 before #188#191.

This PR exposes only the existing definition importer. It does not add goal execution.

What changed

  • add authenticated POST /api/projects/:id/verification-goals/import
  • require the current project owner and hide archived/inaccessible projects
  • apply the Epic 172 project-management ingress gate before project or filesystem work
  • accept no request body and no caller-supplied path, goal, operation, arguments, catalog, or policy
  • canonicalize UUIDs before access, import, persistence, and response serialization
  • return deterministic inserted/existing snapshot results and summary counts
  • map expected importer, registry, and conflict failures to fixed redacted API errors
  • use closed typed importer error codes instead of matching internal exception text
  • document that manual import stores definitions only and never means a goal ran or passed

API contract

Successful imports return schema version 1, the canonical project ID, deterministic snapshot results, and inserted/existing counts. An absent or empty registry is a successful no-op.

Expected failures:

  • 400 invalid_project_id
  • 400 unexpected_request_body
  • 401 unauthorized
  • 404 project_not_found
  • 409 project_context_unavailable
  • 409 project_repository_unavailable
  • 409 definition_version_conflict
  • 422 invalid_verification_goal_registry

Unexpected failures use the existing correlated, redacted 500 boundary.

Deliberately out of scope

  • goal execution or operation dispatch
  • goal-run/outcome/reliability ledgers
  • Redis jobs, schedules, retries, leases, or recovery
  • list/read APIs or dashboard UI
  • automatic import on startup or repository changes
  • editing definitions through HTTP
  • independent Verification Workforce behavior
  • last-green, first-failure, regression, autonomy, or Sentinel state

A future manual runner requires a goal-owned run identity, outcome linkage, project authority model, dedicated queue/lease/recovery contract, and reliability source. It must not synthesize tasks merely to reuse task-owned ledgers.

Local validation

  • focused route, ingress, registry, and importer tests: 55 passed; 4 PostgreSQL-gated tests skipped locally
  • fresh Security-focused suite: 57 passed; 4 PostgreSQL-gated tests skipped locally
  • targeted ESLint: passed
  • TypeScript: passed
  • tracked and untracked diff checks: passed

Review

Fresh orthogonal Review: No blockers found in the inspected scope, high confidence for code and architecture.

Fresh Security/Adversarial review: No blockers found in the inspected scope, high confidence.

The uppercase UUID defect found during Security review was fixed before publication. The earlier message-based error classifier was also replaced with typed importer errors.

Remaining advisories

These are non-blocking for a manual, owner-only, definition-only endpoint, but must be resolved before execution or scheduling depends on imported snapshots:

  • bind project owner, active/archive state, and exact root authority to persistence under a PostgreSQL lock
  • add per-project single-flight plus user/global concurrency, rate, and storage budgets
  • type expected root-binding failures more narrowly so unexpected infrastructure faults reach correlated 500
  • retain an opaque live project-root directory handle before any future execution trust boundary

Hosted proof

Exact-head Web CI run 31827714396 passed:

  • complete zero-skip unit suite
  • PostgreSQL migration, concurrency, and access-control proofs
  • Redis and cross-sink proofs
  • lint and TypeScript
  • production build
  • browser recovery and fail-closed bridge suites

Hosted proof increases confidence but does not remove the explicitly retained definition-only advisories above.

@Joncallim
Joncallim marked this pull request as ready for review August 14, 2026 18:27
@Joncallim
Joncallim merged commit 58a834a into main Aug 14, 2026
4 of 5 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0ed05885a8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// This command has no caller-controlled payload. Reject the presence of a
// body without parsing or consuming it so definitions, paths, or operation
// arguments can never become importer inputs.
if (request.body !== null) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Detect payload bytes instead of the request stream

In the production Node.js route adapter, Next.js wraps every non-GET/HEAD IncomingMessage in a Web request body stream, including a normal POST with Content-Length: 0. Consequently, request.body !== null is true for every real HTTP call and this endpoint always returns 400 unexpected_request_body; the tests miss this because they construct NextRequest directly without the production adapter. Remove this presence check or consume a bounded stream and reject only when it contains bytes.

AGENTS.md reference: web/AGENTS.md:L2-L4

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant