Repository navigation
feat: the interface artifact marks every read as a Runnable operation (x-codefly-operation) - #77
Merged
Merged
Conversation
antoinetoussaint-byte
marked this pull request as ready for review
October 26, 2026 18:36
… (x-codefly-operation) Beside the authority policy of each operation whose policy requires only read, Server.InterfaceArtifact now writes core's x-codefly-operation marker, which core itself derives from that policy (runnable.RouteMarker, core#852). `codefly generate runnables` derives a Runnable package — and so a tool — from every marked route, as it does from every method a module serves behind the hop. - Operation.Exclude keeps a read from every agent, as codefly.runnable.v0.exclude keeps a module's method. The MCP route and every relayed route carry it. - InterfaceDocument marks nothing: the marker names the audience the serving runtime's hop admits, which only the Server knows. A solution must commit Server.InterfaceArtifact's output, and the README and CHANGELOG say so. - Every defined object closes additionalProperties, which core's bounded profile requires of a fixed shape. - Core moves to v0.19.7-0.20261026182446-518714d046af (core#852 merged). Rebased onto main after #78: main's authority-client and hop pins and its Go 1.27.3 bump are kept, core alone moves. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
antoinetoussaint-byte
force-pushed
the
feat/operation-marker
branch
from
October 27, 2026 13:39
5ae58fe to
22723bc
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Second of three PRs for codefly-dev/cli#1184. The interface artifact now publishes
x-codefly-operationbesidex-codefly-authority-policyfor every read a backend serves, socodefly generate runnablesderives each one as a Runnable — and so a tool — exactly as it derives a module's methods.operationMarkerhands core the policy JSON the operation already publishes and gets back the marker (corerunnable.RouteMarker, feat(runnable): a REST read over GET is an operation, and Swagger 2.0 is read as itself core#852): core's default bounds, recomputed on an uncertain outcome, invoked under exactly the scopes the policy requires. The tool's name is the operationId, its description theSummarythe operation is required to carry, and the audienceManifest.ID— the principal this runtime's hop already checks a Work Context against (dialAuthority(…, s.manifest.ID, …)). No vocabulary is invented here. Going throughRouteMarkerwith plain JSON also keeps this package from constructing core's wire messages, whichTestNoCapabilityIsConstructedOrDecodedByType/TestNoWorkContextImplementationGrowsHererefuse (my first version did and they caught it).<path>+ the receipt suffix) that this runtime does not serve; marking one would publish a tool whose uncertain outcome nothing can resolve. So/record,/link/begin,/chat/installbecome nothing, not write tools. Also unmarked: any-checked-caller routes (nothing to mint a capability from), streams, the MCP route (a JSON-RPC envelope, not one operation's input) and relayed routes (another module's call, a tool through that module's own derived operation). A relayed subtree is a path template, which core also refuses.Operation.Excludekeeps a read from every agent, ascodefly.runnable.v0.excludekeeps a module's method. A marked read core cannot carry is refused bygenerate runnablesnaming the route, not silently left unmarked; the owner fixes the shape or excludes it.additionalProperties. Core's bounded profile refuses an object that does not, so without this nothing the runtime publishes would project. It is true of what is described: a struct marshals exactly its fields, and protojson refuses an undeclared one.InterfaceDocumenttrap is named, not refused.InterfaceDocument(the free function) marks nothing — only theServerknows its audience — so a solution committing its output would publish no tool, silently. README (a callout in "Documented operations"), CHANGELOG and its doc comment now say: commitServer.InterfaceArtifact's output, neverInterfaceDocument's. I did not make it refuse: its one outside caller (obin-ai/module-evaluationlibraries/evaluation-client/go/runner/codefly/codefly_test.go:65) uses it to validate an operation, and a refusal would turn every read into an error for documentation-only use. It would also miss the other way to lose every marker, a solution still on a runtime from before this PR. The guard is in feat(generate): a solution's routes become Runnables, and so tools, as a module's methods do (#1184) cli#1185 instead, where the document is read: a document that marks no route although its routes declare read-only policies gets a "not an operation" notice per read, namingServer.InterfaceArtifactas the fix.v0.19.7-0.20261026182446-518714d046af, feat(runnable): a REST read over GET is an operation, and Swagger 2.0 is read as itself core#852's merge commit onmain; thegoline moves to 1.27.3 because that core requires it.Classification
Fix at the owner: the runtime owns the artifact a solution publishes. No stopgap.
Docs
README "Documented operations" (every read is a Runnable operation; what is not marked;
Exclude; closed objects), CHANGELOG Unreleased entry.Blast radius — a regeneration PR in obin-ai/core-solutions
The artifact is committed in consumer repos and CI re-generates it, so bumping to this release changes every consumer's
openapi/api.swagger.jsonandcontracts/api/backend/http/openapi.json(every definition gainsadditionalProperties: false; reads gain the marker). On #451's head, the wiki would gain markers onGET /v1/wiki/upload-accessandGET /v1/wiki/upload-configuration(bothwiki.page:read); proposals has no own read. I have not opened that regeneration PR: obin-ai/core-solutions#451 (open, not a draft) touches exactly those files, and it should land first. The releases solution is on runtime v0.0.15 onmainand declares no policies yet, so its reads become tools once it moves onto the authority runtime.Test plan
go build ./... && go vet ./... && go test -race ./... -count=1andgofmt -l .on the518714d0pin — green (CI's exact steps).runnable_marker_test.go: a releases-shaped server'sInterfaceArtifactmarks exactly its two GET reads, and core derives each from the artifact (PackageFromOpenAPIOperation): the query is the input, read-only, recomputed, described by the Summary; the write, the datasource link and the status are no operation;Excludeunmarks;InterfaceDocumentmarks nothing; every definition is closed.main(6edcb4b7) declared with policies on this branch → artifact marks onlyGET /v1/releases/historyandGET /v1/releases/recorded→ the CLI built from codefly-dev/cli's PR runsgenerate contracts,generate runnables,generate runnable-bindings.Not verified
Part of codefly-dev/cli#1184.
🤖 Generated with Claude Code