v0.2.0 — capability/permission vocabulary split + manifest hardening#3
Merged
Conversation
added 12 commits
May 12, 2026 21:31
…ve A.3 — registry)
…t + fixHint string
…to 'capability' (wave A.5 — vocabulary follow-up)
…permissions[]` and error codes `capability.*` -> `permission.*`
- CapabilityManifest.capabilities -> .permissions (the Permission[] array)
- ActionManifest.capabilities -> .permissions (the PermissionId[] grant list)
- broker fields: capabilityId -> permissionId (NetworkBroker, StorageBroker, ClockBroker, AuditBroker, UiBroker)
- AuditTransport.emit envelope: capabilityId -> permissionId
- replay envelope: capabilityId -> permissionId
- CapabilityError -> PermissionError
- error code rename (inner-permission concerns):
manifest.capabilities.* -> manifest.permissions.*
action.capabilities.* -> action.permissions.*
action.capability_ref.* -> action.permission_ref.*
capability.{not_object,type,duplicate_id,undeclared,denied,no_broker,action.*} -> permission.*
capability.network.{hosts,host_value,methods,method_value,no_transport,bad_url,host_denied,method_denied} -> permission.*
capability.storage.{mode,no_transport,read_denied,write_denied} -> permission.*
capability.audit.no_transport -> permission.audit.no_transport
- fixHints updated to match new vocab
- fixture manifest.ts, smoke.ts, end-to-end.ts updated for field + code assertions
The outer 'capability' identifier (capabilityId, capabilityVersionHash, AuditEventKind 'capability_emit') is unchanged — that remains the manifest-level identifier per the v0.2 vocab split.
Breaking change: manifest hashes change (new shape). Existing approvals will fall back to 'submitted' on first run; require re-approval.
Gate: tsc=0, tests=737/737, demo=24/24.
…nings) - permission.reason.too_short: reason must be >=5 words - action.description.too_short: action description must be >=5 words - permission.network.host_wildcard: no '*' in network hosts - permission.storage.scope_wildcard: no '*' in storage scope - permission.reason.no_action_ref (warning): reason should mention a referencing action id hardenManifest() lives in capability-manifest.ts alongside validateCapabilityManifest().
….warnings submit() now runs hardening after structural validation. If any hardening errors exist it throws ApprovalError on the first one. Warnings are surfaced on the new SubmitResult shape (CapabilityRecord + warnings[]).
Clears the 7 permission.reason.no_action_ref warnings the hardening checks would otherwise surface on the suspicious-transaction-triage demo. Each reason now opens with 'Used by <action.id>' so an approver can trace every grant to its caller.
- Locks the tagline: 'Writmint is a verifier for capabilities an author can't author past.' - 4-beat opener: agent writes manifest with a wildcard host -> submit fails with the verified-real permission.network.host_wildcard error -> fix and resubmit -> run; every brokered call lands in the audit sink. - Updates every API name to v0.2: CapabilityManifest, permissions[], MemoryCapabilityStore, createPermissionRegistry, PermissionError, permission.* error codes, capabilityId (outer wrapper field), scope.cap(). - Mentions hardenManifest() under pillar 1. - Updates test count 737 -> 750.
CHANGELOG entry documents the inner/outer vocabulary split (feature -> capability outer, capabilities[] -> permissions[] inner), manifest hardening (5 rules), and the resulting hash shift requiring re-submit + re-approve for any manifest carried over from v0.1. package.json: version 0.1.0 -> 0.2.0; description rewritten around the locked tagline; keywords swap feature-manifest/capability-scoping for capability-manifest/permission-scoping and add manifest-hardening.
|
Kilo Code Review could not run — your account is out of credits. Add credits or switch to a free model to enable reviews on this change. |
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.
A breaking release. Splits the public-API vocabulary into an outer identity layer (the capability — the manifest as a unit of governance) and an inner permission layer (the individual grants the manifest declares). Adds manifest hardening that runs at submit-time so an agent gets a structured rejection before approval, not after.
Breaking changes
Outer identity layer renamed: feature → capability
FeatureManifestCapabilityManifestMemoryFeatureStoreMemoryCapabilityStoreFeatureStoreinterfaceCapabilityStoreFeatureRecordCapabilityRecordFeatureStatusCapabilityStatusApproveInput.featureIdApproveInput.capabilityIdAuditEvent.featureId/featureVersionHashAuditEvent.capabilityId/capabilityVersionHashAuditEventKindvaluefeature_emitcapability_emit(andcapability_call/capability_denied)approval.unknown_featureapproval.unknown_capabilitysrc/feature-manifest.tssrc/capability-manifest.tsInner permission layer renamed: capabilities[] → permissions[]
CapabilityManifest.capabilities[]permissions[]ActionManifest.capabilities[]permissions[]CapabilityErrorclassPermissionErrorcapabilityId(inner)permissionIdAuditTransport.emit({capabilityId,…})AuditTransport.emit({permissionId,…})createFeatureCapabilityRegistry()createPermissionRegistry()src/capabilities.tssrc/permissions.tscapability.*error codespermission.*(same suffixes)manifest.capabilities.typevalidator codemanifest.permissions.typeaction.capability_ref.type/.unknownaction.permission_ref.type/.unknownThe outer
capabilityIdonAuditEventis manifest identity; the innerpermissionId(also onAuditEvent, and on the broker emit envelope) is the specific permission entry the event came through. Both fields ride on every event.Hash shift
hashManifest()is unchanged in algorithm, but every shipped manifest will produce a differentversionHashunder v0.2 because the renamed object keys (permissions[], etc.) are part of the canonical hash input. Re-submit and re-approve any manifest carried over from v0.1.Added
hardenManifest()(src/capability-manifest.ts) — runs after structural validation. Five rules:permission.reason.too_short— reason ≥ 5 words.action.description.too_short— description ≥ 5 words.permission.network.host_wildcard— no `*` in any host.permission.storage.scope_wildcard— no `*` in any scope.permission.reason.no_action_ref(warning) — every permission's reason should mention an action that references it.ApprovalLifecycle.submit()now runs hardening and throwsApprovalErroron the first hardening error. New return shapeSubmitResultextendsCapabilityRecordwithwarnings: ManifestWarning[].Changed
fixtures/suspicious-transaction-triage/manifest.ts— everypermission.reasonnow opens with "Used by<action.id>…"; fixture passes hardening with 0 errors, 0 warnings.Test plan
npx tsc --noEmit— 0 errorsnpx vitest run— 750 / 750 (48 files)npm run demo— 24 / 24 e2e phases pass; 54 demo assertions totalnpm run build— cleannpm pack --dry-run— writmint@0.2.0 · 81.4 kB · 93 files · ships onlydist/ LICENSE NOTICE README.md package.jsonhardenManifest,ManifestWarning,SubmitResult,PermissionError,createPermissionRegistryall exported; no stalefeature-manifest.*orcapabilities.*artifacts2 audit events captured)permission.network.host_wildcardmatches code/where/expected/actual exactlyMigration for any v0.1 consumer
capabilities→permissionsin every manifest object (outer and inside actions).reasonor actiondescriptionshorter than 5 words; remove any wildcard hosts/scopes; consider adding the referencing action id to each reason to clear the no-action-ref warning.