Skip to content

feat(openapi-mcp): expose complete catalog release admission - #27

Merged
Adam Poulemanos (bashandbone) merged 2 commits into
mainfrom
feat/openapi-catalog-admission
Sep 6, 2026
Merged

feat(openapi-mcp): expose complete catalog release admission#27
Adam Poulemanos (bashandbone) merged 2 commits into
mainfrom
feat/openapi-catalog-admission

Conversation

@bashandbone

@bashandbone Adam Poulemanos (bashandbone) commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

What

Add public admitCatalogRelease(options, catalogId, releaseId) to @knitli/openapi-mcp/runtime. Admission now has a supported entry point that verifies the complete executable release inventory before performing CAS-backed generation admission. A missing unreferenced operation or corrupt schema rejects the release without accepting its generation.

The helper composes the existing executable verification/admission primitives, exports through the public runtime entry point, and is exercised through packed Node/Bun and Worker consumers. The README documents the immutable-storage and use-time verification boundary. This PR does not change package versions or release configuration; publication remains a separate release step.

Plugin(s) affected

  • None; this changes the packages/openapi-mcp package.

Validation

  • Full runtime suite: 224 tests passed, 679 assertions across six files.
  • Admission file: eight tests passed, including changed manifest/inventory after preflight, CAS retry, corruption during retry, and coherent competing higher-generation state.
  • Packed consumers: four tests passed, 32 assertions, including Node/Bun and Worker runtime imports.
  • Package build, scoped Biome checks, and git diff --check passed.
  • mise exec -- bun run validate passed; generated files are in sync.
  • Mutation proof: in a scratch copy, replaced complete executable admission with manifest-only admission. The missing-operation and corrupt-schema tests both failed specifically because generation acceptance occurred (expected 0, received 1). The unmodified admission file and full runtime suite passed afterward.

Checklist

  • Commit message follows the package's conventional commit scope.
  • Marketplace validation passes locally.
  • Package README updated for the public helper.
  • Version and release metadata remain managed by the existing release process.

Related implementation PRs: wrapper catalog/search and host binding. Publication and consumer adoption remain separate steps.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 6, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-06T01:32:18.429408Z 933a843 PR opened
🔒 Security Review Completed 2026-09-06T01:33:45.244737Z 933a843 PR opened
ℹ️ About Codex in GitHub

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

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Comment thread packages/openapi-mcp/README.md Outdated
Comment on lines +375 to +384
### Complete release admission

`admitCatalogRelease(options, catalogId, releaseId)` from
`@knitli/openapi-mcp/runtime` verifies every signed inventory operation and
schema before admitting the generation through the configured `GenerationStore`.
It revalidates the manifest and inventory around generation CAS retries. Use
this supported portable API when activating an executable catalog; `admitManifest`
retains its signed-envelope-only contract. Storage must preserve immutable release
identities. Admission does not guarantee future availability, so runtime reads
continue verifying records at use time.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nit: this new "Complete release admission" section is nested under ## Release gates, which is entirely about npm package publication (protected npmrelease environment, OIDC, registry verification, etc.) — a different "release" concept from the OpenAPI catalog release/generation this section documents. Nesting it here reads as if admitCatalogRelease is part of the publish-gating process, which it isn't.

Consider moving this under ## Recover from a bad release (which already documents admitManifest, generations, and rollback for catalog releases) or its own top-level ## section, so it sits next to the concept it actually belongs to.

@knitli-agent

knitli-agent Bot commented Sep 6, 2026

Copy link
Copy Markdown

🧶 Knitli Agent · PR Reviewer

Clean, well-tested addition. admitCatalogRelease is a thin, correct composition of the existing verifyExecutableRelease + admitExecutableRelease primitives — matching the pattern already proven in src/stdio/index.ts, and it's kept off the public surface until now (verifyExecutableRelease/admitExecutableRelease still aren't exported from runtime/index.ts). Traced the double full-verification (preflight, then re-verify inside the CAS retry loop) and it's intentional, pre-existing behavior, not a regression. New test file exercises the missing-operation, corrupt-schema, post-preflight-mutation, lost-CAS-retry, and concurrent-higher-generation cases well.

  • No blocking issues found.
  • One inline nit: the new README section ("Complete release admission") is nested under ## Release gates, which is about npm package publication, not catalog releases — suggest moving it under ## Recover from a bad release instead.

@bashandbone
Adam Poulemanos (bashandbone) merged commit 3806f6a into main Sep 6, 2026
10 checks passed
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

🎉 This PR is included in version 1.1.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Adam Poulemanos (bashandbone) added a commit to knitli/knitli-os that referenced this pull request Sep 6, 2026
## What does this change?

Adds Knitli's OpenAPI host binding foundation. An authenticated
configurator can issue a draft for its intended workspace; the host
resolves the stored canonical resource URL, reserves and activates the
matching facet, and captures a restricted dispatch capability. Account
disconnection, facet removal, and workspace deletion fence further use
and retain durable cleanup state until acknowledgement.

The implementation includes transactional approval-queue insertion
guards, account-incarnation and generation checks, cleanup-only
revocation capabilities, and an opt-in connector fixture exercised
through real authenticated `/api` Cap'n Web sessions. Kernel/shared
changes and UI wiring are separated into commits for review.

Custom implementation and test files carry precise fork-audit
exemptions. Upstream integration files remain audited; no broad
exemption hides their changes.

Account disconnect delivers recipient workspace fences and completes
connector cleanup before invoking provider revocation. A failed
recipient remains durably pending and prevents the provider operation;
the final account mutation still checks the exact lifecycle epoch.
Remote fencing takes effect on recipient arrival, not atomically with
the User-side fence.

OpenAPI alarm recovery runs only when its own deadline is due and
retries pending bindings, leaving healthy published connections
untouched. Constructor-driven recovery still replays all bindings after
restart. Legacy and OpenAPI resource resolution share one private User
policy-enforcement helper, documented in `AGENTS.md`, so
deployment-policy corrections apply to both paths.

The private host facet, draft authority, dispatch-use authority, and
acknowledgement-only revoker now use named `@validateRpc()` targets with
private captured state. Malformed arguments fail generated validation
before lifecycle reads or writes. Fixture protocol targets are also
decorated, and the new protocol methods no longer bypass validation. The
draft handoff uses a scoped native stub; recipients duplicate
capabilities they retain.

A pinned `capnweb-validate@0.3.0` patch preserves native Workers
capability transport: its original transform wrapped returned native
stubs in JavaScript proxies, breaking subsequent RPC calls. Both ESM and
CJS transforms now distinguish Workers brand declarations from Cap'n Web
declarations. Native capabilities retain stub validation and transport
identity; their owning decorated endpoint enforces method arguments.
Ordinary Cap'n Web capabilities retain service wrapping. The patch and
its regression test have exact fork-audit exemptions.

Agent keepalive scheduling now retains the deadline established when the
first agent starts. OpenAPI recovery and response updates continue
choosing the earliest shared alarm without restarting that minute.
Last-agent completion clears the agent deadline and retains any
response/OpenAPI deadline. The alarm handler itself is unchanged.

Restart recovery preserves previously published bindings across
transient lookup, activation, and description/publication failures. The
constructor marks all persisted published bindings `recoveryPending`
before its first recovery await. These bindings retain their identity
and remain unavailable to public entry points and dispatch use until the
full replay succeeds. Private dispatch-key registration can proceed
during replay. Pending rows participate in the existing alarm retries,
and a late failed lookup cannot revoke a binding another replay already
recovered. Locally established semantic invalidation still fences;
failed new creation still cleans up. Both recovery warning paths now
include the caught error through the typed logger, retaining diagnostic
message and stack.

Recovery now starts independent account drafts and binding replays
concurrently, with the durable retry alarm armed before external work. A
real 10-second timer bounds each recovery wait. The entire attempt,
including lookup, retains its per-key slot until the underlying
operation settles, so repeated alarms cannot accumulate duplicate
hanging RPCs. Expired attempts cannot activate, publish, or provide
usable dispatch authority; late lookup results release their finalizer.
Timeout preserves pending state rather than treating a published grant
as invalid. Safe revocation acknowledgements may finish late. The
removal warning now also includes its caught exception through the typed
logger.

## Review and validation

This feature is for `knitli/knitli-os`; custom files have precise fork
exemptions and upstream integration files remain audited. Independent
review covered lifecycle behavior, capability scope, native stub
ownership, and the dependency compatibility patch.

- Full build: 70 tasks passed, including production validator
generation.
- Full tests: 169 script tests and 2,406 Vitest tests passed, with seven
existing skips and one expected failure. This includes 736 backend tests
and 63 integration tests.
- All 22 authenticated OpenAPI acceptance cases passed, with no skips or
unhandled errors.
- Lint, script type checking, and the fork merge audit passed.
- Actual RPC regressions reject malformed dispatch-key requests,
activation digests, draft registration/cancellation, proof-revocation
reasons, selection inputs, and session writes before lifecycle effects.
- The transform regression exercises distinct public ESM and CJS
plugins, checks native `stub` versus Cap'n Web `stubOf` output, and
checks the production zero-argument dispatch authority's generated
validator structurally.

Sensitivity checks ran in isolated scratch copies. Removing the facet
decorator caused seven intended assertion failures; removing the
draft-authority decorator caused two, and removing the proof-revoker
decorator caused one. Removing fixture selection or session validation
failed their respective authenticated assertions. Using the original
unpatched ESM/CJS transforms caused two native-capability shape
failures; removing the zero-argument authority decorator caused two
structural failures. Restoring each change returned the relevant full
files to green.

Agent-deadline regressions exercise real agent
registration/unregistration, OpenAPI recovery, response scheduling, and
an alarm handler waiting for completion. The final full facet file
passed all 64 tests. In an isolated scratch copy, restoring the original
implementation caused three deadline assertion failures: OpenAPI and
response updates each postponed the deadline by 10 seconds, and an
update during the waiting alarm postponed it by 60 seconds. Restoring
the fix returned all 64 tests to green. Tests use explicit timestamps to
check stored scheduling decisions, not elapsed workerd wall-clock time.

Restart regressions cover constructor marking of multiple bindings,
lookup/activation/description failures and successful retry, repeated
Add, late overlapping lookup failure, and dispatch availability during
recovery. The facet/dispatch files pass 89 tests. Restoring the original
source in an isolated scratch copy causes seven regression failures;
restoring the fix returns all 89 to green. A separate narrow mutation
removes the dispatch-use guard and fails specifically because pending
`use.assertActive()` incorrectly resolves; restoring it returns all 89
to green.

Earlier sensitivity checks also cover captured generation, account
readiness, final transactional insertion, public workspace deletion,
recipient fencing before provider revocation, alarm
deadline/pending-only recovery, and shared deployment-policy
enforcement. Full final suites passed after all fixes.

Blueprint regression coverage includes eight backend setup tests, two
additional authenticated acceptance cases, and 15 focused UI tests.
Eight narrow helper mutations fail their intended assertions. Removing
the preallocation guard produces the wrong error and an extra workspace;
restoring it returns all 22 acceptance cases to green. UI mutations
cover suggested-URL bypass, explicit deferral, original binding names,
dependent retries, workspace/gadget scoping, account preference, and
both sides of owner-only panel visibility. All mutations ran in isolated
scratch copies and were restored to green.

Recovery isolation regressions run through the production timer
mechanism and actual Overseer alarm path. They cover hung lookup,
activation and publication, healthy bindings and historical drafts
alongside a stuck account draft, no overlapping retries after expiry,
and retained dispatch authority remaining expired after a later
successful replay. The prior overlap-oriented lookup regression now
requires one shared in-flight attempt, matching the new contract. Tests
capture and invoke the actual timer callback and assert its configured
delay; they do not infer elapsed time from workerd's frozen request
clock.

Six isolated scratch mutations triggered the intended assertions:
restoring sequential recovery blocked a healthy binding; serializing
account drafts left healthy historical cleanup pending; removing early
scheduling left the retry alarm unarmed; releasing an expired attempt's
slot started a duplicate operation; removing the attempt guard permitted
late continuation; removing the dispatch-use guard let an expired
capability succeed after recovery. Restoring source returned the full
facet file to 77 passing tests. Harness and compilation failures were
excluded from this evidence. An additional test-file-inclusive type
check found the same two pre-existing fixture errors (partial
DurableObjectNamespace cast and ObservationDescription.text) as the
preceding commit, with no new errors; repository build and script type
checks pass.

## Scope and follow-up

A permanently unresolved connector operation requires settlement or a
Durable Object restart before that same key can retry. This bounds
waiting and isolates healthy siblings without claiming remote RPC
cancellation. A separately running user Add that recovery joins remains
independently authorized.

Blueprint retry guarantees apply to durably saved resource IDs and
binding progress. The existing resource creation APIs can leave an
unused workpiece if execution stops after creation but before its ID is
saved; this change does not promise duplicate-free creation across
arbitrary process termination.

The authenticated reload scenario changes Worker configuration while
retaining storage and then logs in again; it is not a process-restart or
explicit eviction test. Separate workerd tests exercise Durable Object
eviction and persistence. Fixture leases establish protocol
admission/drain ordering, not physical provider I/O; expiry checks use
explicit injected or persisted timestamps rather than elapsed workerd
wall-clock assertions.

This PR does not add native provider action execution, the wrapper's
native connector/search implementation, publication, deployment, or a
wrapper gitlink update. Those remain follow-on integration work. The
private connector contract requires an immutable `resourceUrl` and an
exact-reference cleanup-only revoker that remains usable after account
revocation.

Related implementation PRs: [portable admission
helper](knitli/toolshed#27) and [wrapper
catalog/search](knitli/knitli-site#322). Wrapper
pin adoption and the real native connector remain separate steps.

The published runtime is adopted separately in [knitli/knitli-site
cloudflare#323](knitli/knitli-site#323).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant