@openwop/spec-artifacts 2.46.20 → 2.46.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CORPUS-STAMP.json +25 -21
- package/api/seams-v2.yaml +1 -1
- package/api/v2/asyncapi.yaml +1 -1
- package/api/v2/openapi.yaml +430 -1
- package/package.json +1 -1
- package/schemas/v2/capabilities.schema.json +20 -1
- package/schemas/v2/error-envelope.schema.json +78 -3
- package/schemas/v2/proposal-apply.schema.json +15 -0
- package/schemas/v2/proposal-list-response.schema.json +25 -0
- package/schemas/v2/proposal-revise.schema.json +24 -0
- package/schemas/v2/proposal-submit.schema.json +37 -0
- package/schemas/v2/proposal.schema.json +45 -4
- package/spec/v1/core-standard-manifest.json +2 -2
- package/spec/v1/gaps.json +89 -4
- package/spec/v2/core/errors.md +2 -2
- package/spec/v2/core/headers.md +5 -5
- package/spec/v2/core/security-defaults.md +3 -2
- package/spec/v2/errors.json +45 -0
- package/spec/v2/facets/agents.schema.json +20 -1
- package/spec/v2/generated/error-codes.md +4 -1
- package/spec/v2/id-field-bindings.json +1 -0
- package/spec/v2/path-manifest.json +80 -1
- package/spec/v2/release.json +2 -2
- package/spec/v2/surface-baseline.json +82 -2
|
@@ -3532,7 +3532,7 @@
|
|
|
3532
3532
|
},
|
|
3533
3533
|
"proposals": {
|
|
3534
3534
|
"type": "object",
|
|
3535
|
-
"description": "RFC 0096 (`Active`). Reviewable learning — the host synthesizes reusable artifacts (skills/packs/templates/automations) from run/tool traces as INERT, reviewable drafts that MUST NOT influence the resolution, planning, or execution of any run until an authorized principal activates them.
|
|
3535
|
+
"description": "RFC 0096 (`Active`), operations by RFC 0249. Reviewable learning — the host synthesizes reusable artifacts (skills/packs/templates/automations) from run/tool traces as INERT, reviewable drafts that MUST NOT influence the resolution, planning, or execution of any run until an authorized principal activates them. The surface is the seven `proposals` operations (`listProposals`, `getProposal`, `submitProposal`, `reviseProposal`, `applyProposal`, `rejectProposal`, `archiveProposal`; scopes `proposals:read`, `proposals:write`, `proposals:apply`); a host that omits this block answers each as `errors.md` §Unadvertised operations requires. A proposal another tenant owns MUST be answered exactly as an unknown id. `applied`, `rejected` and `archived` are terminal: revise, apply or reject on one, and archive on `applied` or `archived`, is refused `409 proposal_state_conflict`. A host advertising this emits the content-free `proposal.created` / `proposal.activated` events. Activation is delegated to RFC 0051 approval-gate (apply opens a gate run that suspends on an `approval` interrupt) or RFC 0049 RBAC (`proposals:apply`) — no new authorization path. On `apply` the installed artifact MUST byte-match the last-persisted `artifact` (no silent re-synthesis); `activation.installedArtifact` names the read that shows it. The redaction-safety of `rationale` and `provenance.sourceRunIds` and the lifecycle are in `proposal.schema.json`.",
|
|
3536
3536
|
"additionalProperties": false,
|
|
3537
3537
|
"required": [
|
|
3538
3538
|
"artifactKinds",
|
|
@@ -3565,6 +3565,25 @@
|
|
|
3565
3565
|
"direct-rbac"
|
|
3566
3566
|
],
|
|
3567
3567
|
"description": "`approval-gate`: `apply` MUST drive an RFC 0051 gate (role/scope/quorum, audited override) and MUST NOT install unless granted/overridden. `direct-rbac`: `apply` requires only the RFC 0049 scope the host advertises for activation. An `overridden` gate MUST be audited."
|
|
3568
|
+
},
|
|
3569
|
+
"clientDrafts": {
|
|
3570
|
+
"type": "boolean",
|
|
3571
|
+
"default": false,
|
|
3572
|
+
"description": "RFC 0249 §B. When `true`, `submitProposal` accepts a client-authored draft. A submitted draft MUST be held to every rule a synthesized one is, inertness first, with `provenance.sourceRunIds: []`. Absent or `false`, `submitProposal` answers `404 not_found`."
|
|
3573
|
+
},
|
|
3574
|
+
"readback": {
|
|
3575
|
+
"type": "array",
|
|
3576
|
+
"uniqueItems": true,
|
|
3577
|
+
"items": {
|
|
3578
|
+
"type": "string",
|
|
3579
|
+
"enum": [
|
|
3580
|
+
"agent-pack",
|
|
3581
|
+
"workflow-chain-pack",
|
|
3582
|
+
"prompt-template",
|
|
3583
|
+
"automation"
|
|
3584
|
+
]
|
|
3585
|
+
},
|
|
3586
|
+
"description": "RFC 0249 §D. The kinds whose installed artifact resolves through `activation.installedArtifact`; a subset of `artifactKinds`. For `prompt-template` the read is `getPromptTemplate`, only `meta` is host-owned, and while a proposal is unapplied `getPromptTemplate` / `listPromptTemplates` MUST NOT serve a template carrying its `(templateId, version)` and `POST /prompts:render` naming it MUST fail as for an unknown template. Install follows the prompts write in the applying tenant, and a refused install is `409 proposal_install_conflict`. A kind proposed but absent here has no outside read-back: its RFC 0096 rules bind but are not checkable from the wire (`workflow-chain-pack`, `agent-pack` and `automation` have no read-back at v2 today)."
|
|
3568
3587
|
}
|
|
3569
3588
|
}
|
|
3570
3589
|
},
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://openwop.dev/spec/v2/error-envelope.schema.json",
|
|
4
4
|
"title": "ErrorEnvelope (v2)",
|
|
5
|
-
"description": "GENERATED from spec/v2/errors.json by scripts/generate-error-envelope.mjs (RFC 0171 §B.1).
|
|
5
|
+
"description": "GENERATED from spec/v2/errors.json by scripts/generate-error-envelope.mjs (RFC 0171 §B.1). 125 registered codes; vendor codes match ^(?!openwop\\.)[a-z][a-z0-9]*(-[a-z0-9]+)*\\.[a-z][a-z0-9_]*$. Consumers MUST accept an unknown registered member and MUST NOT act on it (RFC 0171 §A.5).",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"additionalProperties": false,
|
|
8
8
|
"required": [
|
|
@@ -136,7 +136,10 @@
|
|
|
136
136
|
"provider_policy_denied",
|
|
137
137
|
"eval_gate_unmet",
|
|
138
138
|
"conversation_speaker_not_participant",
|
|
139
|
-
"conversation_roster_exceeded"
|
|
139
|
+
"conversation_roster_exceeded",
|
|
140
|
+
"proposal_state_conflict",
|
|
141
|
+
"proposal_stale",
|
|
142
|
+
"proposal_install_conflict"
|
|
140
143
|
]
|
|
141
144
|
},
|
|
142
145
|
{
|
|
@@ -618,6 +621,75 @@
|
|
|
618
621
|
}
|
|
619
622
|
}
|
|
620
623
|
}
|
|
624
|
+
},
|
|
625
|
+
{
|
|
626
|
+
"if": {
|
|
627
|
+
"properties": {
|
|
628
|
+
"error": {
|
|
629
|
+
"const": "proposal_state_conflict"
|
|
630
|
+
}
|
|
631
|
+
},
|
|
632
|
+
"required": [
|
|
633
|
+
"error"
|
|
634
|
+
]
|
|
635
|
+
},
|
|
636
|
+
"then": {
|
|
637
|
+
"properties": {
|
|
638
|
+
"details": {
|
|
639
|
+
"type": "object",
|
|
640
|
+
"required": [
|
|
641
|
+
"state",
|
|
642
|
+
"action"
|
|
643
|
+
],
|
|
644
|
+
"properties": {
|
|
645
|
+
"state": {
|
|
646
|
+
"type": "string",
|
|
647
|
+
"description": "The proposal's current state."
|
|
648
|
+
},
|
|
649
|
+
"action": {
|
|
650
|
+
"type": "string",
|
|
651
|
+
"description": "The refused action: revise, apply or reject."
|
|
652
|
+
}
|
|
653
|
+
},
|
|
654
|
+
"additionalProperties": true,
|
|
655
|
+
"x-openwop-error": "proposal_state_conflict"
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
},
|
|
660
|
+
{
|
|
661
|
+
"if": {
|
|
662
|
+
"properties": {
|
|
663
|
+
"error": {
|
|
664
|
+
"const": "proposal_install_conflict"
|
|
665
|
+
}
|
|
666
|
+
},
|
|
667
|
+
"required": [
|
|
668
|
+
"error"
|
|
669
|
+
]
|
|
670
|
+
},
|
|
671
|
+
"then": {
|
|
672
|
+
"properties": {
|
|
673
|
+
"details": {
|
|
674
|
+
"type": "object",
|
|
675
|
+
"required": [
|
|
676
|
+
"reason"
|
|
677
|
+
],
|
|
678
|
+
"properties": {
|
|
679
|
+
"reason": {
|
|
680
|
+
"type": "string",
|
|
681
|
+
"enum": [
|
|
682
|
+
"version-not-greater",
|
|
683
|
+
"read-only"
|
|
684
|
+
],
|
|
685
|
+
"description": "Why the store refused (RFC 0249 §D)."
|
|
686
|
+
}
|
|
687
|
+
},
|
|
688
|
+
"additionalProperties": true,
|
|
689
|
+
"x-openwop-error": "proposal_install_conflict"
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
}
|
|
621
693
|
}
|
|
622
694
|
],
|
|
623
695
|
"x-openwop-http-status": {
|
|
@@ -742,7 +814,10 @@
|
|
|
742
814
|
"provider_policy_denied": 422,
|
|
743
815
|
"eval_gate_unmet": 422,
|
|
744
816
|
"conversation_speaker_not_participant": 422,
|
|
745
|
-
"conversation_roster_exceeded": 422
|
|
817
|
+
"conversation_roster_exceeded": 422,
|
|
818
|
+
"proposal_state_conflict": 409,
|
|
819
|
+
"proposal_stale": 409,
|
|
820
|
+
"proposal_install_conflict": 409
|
|
746
821
|
},
|
|
747
822
|
"x-openwop-retriable": [
|
|
748
823
|
"residency_unavailable",
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://openwop.dev/spec/v2/proposal-apply.schema.json",
|
|
4
|
+
"title": "ProposalApply",
|
|
5
|
+
"description": "RFC 0249 §C. The optional `applyProposal` body binding the apply to the bytes the reviewer read. A host MAY require it (`400 validation_error`, `details.field: artifactDigest`). A digest that differs from the proposal's current `artifactDigest` MUST be refused `409 proposal_stale`, installing nothing.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"properties": {
|
|
9
|
+
"artifactDigest": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"pattern": "^sha256:[0-9a-f]{64}$",
|
|
12
|
+
"description": "`sha256:` + lowercase hex SHA-256 of the RFC 8785 (JCS) serialization of the reviewed `artifact`."
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://openwop.dev/spec/v2/proposal-list-response.schema.json",
|
|
4
|
+
"title": "ProposalListResponse",
|
|
5
|
+
"description": "RFC 0249 §A. One page of `listProposals`, scoped to the caller's tenant and workspace; a proposal another tenant owns never appears.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"items"
|
|
10
|
+
],
|
|
11
|
+
"properties": {
|
|
12
|
+
"items": {
|
|
13
|
+
"type": "array",
|
|
14
|
+
"items": {
|
|
15
|
+
"$ref": "proposal.schema.json"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"nextCursor": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"minLength": 1,
|
|
21
|
+
"maxLength": 2048,
|
|
22
|
+
"description": "Opaque cursor for the next page; absent on the last."
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://openwop.dev/spec/v2/proposal-revise.schema.json",
|
|
4
|
+
"title": "ProposalRevise",
|
|
5
|
+
"description": "RFC 0249 §A. The `reviseProposal` body. Sets `state: revised` and MUST NOT activate. Refused `409 proposal_state_conflict` on a terminal proposal (`applied`, `rejected`, `archived`) and `409 proposal_stale` on a lost concurrent update.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"minProperties": 1,
|
|
9
|
+
"properties": {
|
|
10
|
+
"artifact": {
|
|
11
|
+
"type": "object",
|
|
12
|
+
"additionalProperties": true,
|
|
13
|
+
"description": "The revised artifact, shaped by the proposal's `kind`."
|
|
14
|
+
},
|
|
15
|
+
"title": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "Human-facing label. SR-1 redaction-safe."
|
|
18
|
+
},
|
|
19
|
+
"rationale": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"description": "Plain-language justification. SR-1 redaction-safe."
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://openwop.dev/spec/v2/proposal-submit.schema.json",
|
|
4
|
+
"title": "ProposalSubmit",
|
|
5
|
+
"description": "RFC 0249 §B. The `submitProposal` body: a client-authored draft, accepted only when `agents.proposals.clientDrafts` is `true`. The host MUST refuse a `kind` outside `artifactKinds` with `400 validation_error` (`details.field: kind`), MUST set `provenance.sourceRunIds: []`, and MUST hold the draft to every RFC 0096 rule, inertness first.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"kind",
|
|
10
|
+
"artifact"
|
|
11
|
+
],
|
|
12
|
+
"properties": {
|
|
13
|
+
"kind": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"enum": [
|
|
16
|
+
"agent-pack",
|
|
17
|
+
"workflow-chain-pack",
|
|
18
|
+
"prompt-template",
|
|
19
|
+
"automation"
|
|
20
|
+
],
|
|
21
|
+
"description": "The artifact kind; MUST be one the host advertises in `artifactKinds`."
|
|
22
|
+
},
|
|
23
|
+
"artifact": {
|
|
24
|
+
"type": "object",
|
|
25
|
+
"additionalProperties": true,
|
|
26
|
+
"description": "The proposed artifact, shaped by `kind`'s own schema. Inert until applied; validated against that schema at apply (`422` on mismatch)."
|
|
27
|
+
},
|
|
28
|
+
"title": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"description": "Human-facing label. SR-1 redaction-safe."
|
|
31
|
+
},
|
|
32
|
+
"rationale": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"description": "Plain-language justification. SR-1 redaction-safe."
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://openwop.dev/spec/v2/proposal.schema.json",
|
|
4
4
|
"title": "Proposal",
|
|
5
|
-
"description": "RFC 0096 §B. A reviewable-learning proposal — an INERT, draft-state reusable artifact (skill/pack/template/automation) the host synthesized from run/tool traces, that MUST NOT influence the resolution, planning, or execution of any run while in any state other than `applied`. Activation is delegated to RFC 0051 approval-gate or RFC 0049 RBAC (no new authorization path). On `apply` the installed artifact MUST byte-match the last-persisted `artifact` (no silent re-synthesis). `rationale` and `provenance.sourceRunIds` are SR-1 redaction-safe (no secrets/PII). Gated on the `agents.proposals` capability.",
|
|
5
|
+
"description": "RFC 0096 §B. A reviewable-learning proposal — an INERT, draft-state reusable artifact (skill/pack/template/automation) the host synthesized from run/tool traces, that MUST NOT influence the resolution, planning, or execution of any run while in any state other than `applied`. Activation is delegated to RFC 0051 approval-gate or RFC 0049 RBAC (no new authorization path). On `apply` the installed artifact MUST byte-match the last-persisted `artifact` (no silent re-synthesis). `rationale` and `provenance.sourceRunIds` are SR-1 redaction-safe (no secrets/PII). Gated on the `agents.proposals` capability. RFC 0249: served by `getProposal` / `listProposals`; on apply, `activation.installedArtifact` names the v2 read that serves the installed bytes, and those bytes minus the kind's host-owned fields MUST be RFC 8785 (JCS) equal to the last-persisted `artifact`.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"additionalProperties": false,
|
|
8
8
|
"required": [
|
|
@@ -55,6 +55,11 @@
|
|
|
55
55
|
"$comment": "Intentionally open object — the artifact body is validated against the kind's own schema, not this envelope.",
|
|
56
56
|
"additionalProperties": true
|
|
57
57
|
},
|
|
58
|
+
"artifactDigest": {
|
|
59
|
+
"type": "string",
|
|
60
|
+
"pattern": "^sha256:[0-9a-f]{64}$",
|
|
61
|
+
"description": "RFC 0249 §C. `sha256:` followed by the lowercase hex SHA-256 of the RFC 8785 (JCS) serialization of `artifact`, recomputed on every revision. `applyProposal` binds to it: a sent digest that differs from this value is refused `409 proposal_stale`."
|
|
62
|
+
},
|
|
58
63
|
"provenance": {
|
|
59
64
|
"type": "object",
|
|
60
65
|
"additionalProperties": false,
|
|
@@ -127,7 +132,44 @@
|
|
|
127
132
|
},
|
|
128
133
|
"installedArtifactRef": {
|
|
129
134
|
"type": "string",
|
|
130
|
-
"description": "
|
|
135
|
+
"description": "Opaque ref of the artifact installed on `apply` (RFC 0043 install path). A client MUST NOT treat it as resolvable; `installedArtifact` is the resolvable form (RFC 0249)."
|
|
136
|
+
},
|
|
137
|
+
"installedArtifact": {
|
|
138
|
+
"type": "object",
|
|
139
|
+
"additionalProperties": false,
|
|
140
|
+
"required": [
|
|
141
|
+
"kind",
|
|
142
|
+
"operationId",
|
|
143
|
+
"id"
|
|
144
|
+
],
|
|
145
|
+
"description": "RFC 0249 §C. The v2 read that serves the installed artifact. `operationId` names a GET operation in `spec/v2/path-manifest.json`, evaluated in the applying tenant's scope; for any other tenant the installed artifact answers as an unknown id. The body that operation returns, with the kind's host-owned fields removed from both sides (`meta` for `prompt-template`), MUST be RFC 8785 (JCS) equal to the `artifact` last persisted before apply.",
|
|
146
|
+
"properties": {
|
|
147
|
+
"kind": {
|
|
148
|
+
"type": "string",
|
|
149
|
+
"enum": [
|
|
150
|
+
"agent-pack",
|
|
151
|
+
"workflow-chain-pack",
|
|
152
|
+
"prompt-template",
|
|
153
|
+
"automation"
|
|
154
|
+
],
|
|
155
|
+
"description": "The installed artifact's kind; equals the proposal's `kind`."
|
|
156
|
+
},
|
|
157
|
+
"operationId": {
|
|
158
|
+
"type": "string",
|
|
159
|
+
"minLength": 1,
|
|
160
|
+
"description": "A GET operation in `spec/v2/path-manifest.json` (for `prompt-template`, `getPromptTemplate`)."
|
|
161
|
+
},
|
|
162
|
+
"id": {
|
|
163
|
+
"type": "string",
|
|
164
|
+
"minLength": 1,
|
|
165
|
+
"description": "The path parameter that operation takes. It MUST be the artifact's own identifier (for `prompt-template`, `artifact.templateId`); a host MUST NOT mint one."
|
|
166
|
+
},
|
|
167
|
+
"version": {
|
|
168
|
+
"type": "string",
|
|
169
|
+
"minLength": 1,
|
|
170
|
+
"description": "The installed version, when the read surface is versioned."
|
|
171
|
+
}
|
|
172
|
+
}
|
|
131
173
|
}
|
|
132
174
|
}
|
|
133
175
|
},
|
|
@@ -139,6 +181,5 @@
|
|
|
139
181
|
"type": "string",
|
|
140
182
|
"format": "date-time"
|
|
141
183
|
}
|
|
142
|
-
}
|
|
143
|
-
"x-openwop-seeded-from": "v1"
|
|
184
|
+
}
|
|
144
185
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"provenance": {
|
|
5
5
|
"suite": {
|
|
6
6
|
"package": "@openwop/openwop-conformance",
|
|
7
|
-
"version": "2.46.
|
|
7
|
+
"version": "2.46.22"
|
|
8
8
|
},
|
|
9
9
|
"note": "Derived from the corpus at generation time. Regenerate with --write; verify with --check."
|
|
10
10
|
},
|
|
@@ -426,5 +426,5 @@
|
|
|
426
426
|
"$id": "https://openwop.dev/spec/v1/workspace-file.schema.json"
|
|
427
427
|
}
|
|
428
428
|
],
|
|
429
|
-
"digest": "
|
|
429
|
+
"digest": "0e1987ad303a3834d8466302554886144025df13513c74d1e6ba9b4728e4c155"
|
|
430
430
|
}
|
package/spec/v1/gaps.json
CHANGED
|
@@ -14858,11 +14858,11 @@
|
|
|
14858
14858
|
"rfc": "0249",
|
|
14859
14859
|
"local": "G1",
|
|
14860
14860
|
"section": "§Conformance",
|
|
14861
|
-
"surface": "No host implements the seven operations. openwop-app does not advertise `agents.proposals`; MyndHyve advertises it at v1 only.
|
|
14861
|
+
"surface": "No host implements the seven operations. openwop-app does not advertise `agents.proposals`; MyndHyve advertises it at v1 only. openwop-app builds phase 1 (ADR 0970, user-directed 2026-10-24).",
|
|
14862
14862
|
"witness": "unclassified",
|
|
14863
14863
|
"requirementId": null,
|
|
14864
|
-
"disposition": "
|
|
14865
|
-
"target":
|
|
14864
|
+
"disposition": "closed",
|
|
14865
|
+
"target": null,
|
|
14866
14866
|
"sources": [
|
|
14867
14867
|
{
|
|
14868
14868
|
"file": "RFCS/registers/0249-proposal-operations-and-install-readback.gaps.md",
|
|
@@ -14929,11 +14929,96 @@
|
|
|
14929
14929
|
"surface": "Submit scope, approval-gate shape, `readback` vs implied, the terminal-state error code, and the complete host-owned field set for `prompt-template`.",
|
|
14930
14930
|
"witness": "unclassified",
|
|
14931
14931
|
"requirementId": null,
|
|
14932
|
+
"disposition": "closed",
|
|
14933
|
+
"target": null,
|
|
14934
|
+
"sources": [
|
|
14935
|
+
{
|
|
14936
|
+
"file": "RFCS/registers/0249-proposal-operations-and-install-readback.gaps.md",
|
|
14937
|
+
"token": "G5"
|
|
14938
|
+
}
|
|
14939
|
+
]
|
|
14940
|
+
},
|
|
14941
|
+
{
|
|
14942
|
+
"id": "openwop.gap.0250.1",
|
|
14943
|
+
"rfc": "0250",
|
|
14944
|
+
"local": "G1",
|
|
14945
|
+
"section": "A/C",
|
|
14946
|
+
"surface": "Facet/query/error names and status",
|
|
14947
|
+
"witness": "unclassified",
|
|
14948
|
+
"requirementId": null,
|
|
14932
14949
|
"disposition": "transferred",
|
|
14933
14950
|
"target": "TODO.md",
|
|
14934
14951
|
"sources": [
|
|
14935
14952
|
{
|
|
14936
|
-
"file": "RFCS/registers/
|
|
14953
|
+
"file": "RFCS/registers/0250-opt-in-host-event-replay-and-resync.gaps.md",
|
|
14954
|
+
"token": "G1"
|
|
14955
|
+
}
|
|
14956
|
+
]
|
|
14957
|
+
},
|
|
14958
|
+
{
|
|
14959
|
+
"id": "openwop.gap.0250.2",
|
|
14960
|
+
"rfc": "0250",
|
|
14961
|
+
"local": "G2",
|
|
14962
|
+
"section": "A/D",
|
|
14963
|
+
"surface": "Retention and lawful deletion/revocation exceptions",
|
|
14964
|
+
"witness": "unclassified",
|
|
14965
|
+
"requirementId": null,
|
|
14966
|
+
"disposition": "transferred",
|
|
14967
|
+
"target": "TODO.md",
|
|
14968
|
+
"sources": [
|
|
14969
|
+
{
|
|
14970
|
+
"file": "RFCS/registers/0250-opt-in-host-event-replay-and-resync.gaps.md",
|
|
14971
|
+
"token": "G2"
|
|
14972
|
+
}
|
|
14973
|
+
]
|
|
14974
|
+
},
|
|
14975
|
+
{
|
|
14976
|
+
"id": "openwop.gap.0250.3",
|
|
14977
|
+
"rfc": "0250",
|
|
14978
|
+
"local": "G3",
|
|
14979
|
+
"section": "B",
|
|
14980
|
+
"surface": "Stable replay order and atomic live handoff",
|
|
14981
|
+
"witness": "unclassified",
|
|
14982
|
+
"requirementId": null,
|
|
14983
|
+
"disposition": "transferred",
|
|
14984
|
+
"target": "TODO.md",
|
|
14985
|
+
"sources": [
|
|
14986
|
+
{
|
|
14987
|
+
"file": "RFCS/registers/0250-opt-in-host-event-replay-and-resync.gaps.md",
|
|
14988
|
+
"token": "G3"
|
|
14989
|
+
}
|
|
14990
|
+
]
|
|
14991
|
+
},
|
|
14992
|
+
{
|
|
14993
|
+
"id": "openwop.gap.0250.4",
|
|
14994
|
+
"rfc": "0250",
|
|
14995
|
+
"local": "G4",
|
|
14996
|
+
"section": "Conformance",
|
|
14997
|
+
"surface": "Causable restart/trim/oversize tests without public backdoor",
|
|
14998
|
+
"witness": "unclassified",
|
|
14999
|
+
"requirementId": null,
|
|
15000
|
+
"disposition": "transferred",
|
|
15001
|
+
"target": "TODO.md",
|
|
15002
|
+
"sources": [
|
|
15003
|
+
{
|
|
15004
|
+
"file": "RFCS/registers/0250-opt-in-host-event-replay-and-resync.gaps.md",
|
|
15005
|
+
"token": "G4"
|
|
15006
|
+
}
|
|
15007
|
+
]
|
|
15008
|
+
},
|
|
15009
|
+
{
|
|
15010
|
+
"id": "openwop.gap.0250.5",
|
|
15011
|
+
"rfc": "0250",
|
|
15012
|
+
"local": "G5",
|
|
15013
|
+
"section": "E",
|
|
15014
|
+
"surface": "SDK owners/minors and application baseline reconciliation",
|
|
15015
|
+
"witness": "unclassified",
|
|
15016
|
+
"requirementId": null,
|
|
15017
|
+
"disposition": "transferred",
|
|
15018
|
+
"target": "TODO.md",
|
|
15019
|
+
"sources": [
|
|
15020
|
+
{
|
|
15021
|
+
"file": "RFCS/registers/0250-opt-in-host-event-replay-and-resync.gaps.md",
|
|
14937
15022
|
"token": "G5"
|
|
14938
15023
|
}
|
|
14939
15024
|
]
|
package/spec/v2/core/errors.md
CHANGED
|
@@ -8,7 +8,7 @@ Every error a v2 host returns is a row in one registry. A client routes on `erro
|
|
|
8
8
|
|
|
9
9
|
## The registry
|
|
10
10
|
|
|
11
|
-
`spec/v2/errors.json` holds one row per code, defined by `spec/v2/errors.schema.json`. It registers **
|
|
11
|
+
`spec/v2/errors.json` holds one row per code, defined by `spec/v2/errors.schema.json`. It registers **125** codes. `schemas/v2/error-envelope.schema.json` is GENERATED from it and MUST NOT be edited by hand.
|
|
12
12
|
|
|
13
13
|
- A host MUST emit a registered code, or a vendor code, wherever it emits an error code: the `error` of every error response, and `error.code` on `run.failed`, `node.failed` and the snapshot's `error` (overview.md §0). A recorded event re-emitted by replay or `:fork` is carried as recorded ([replay.md](replay.md)).
|
|
14
14
|
- A vendor code MUST match `^(?!openwop\.)[a-z][a-z0-9]*(-[a-z0-9]+)*\.[a-z][a-z0-9_]*$`, with its first segment an org registered in `spec/v2/declaration.json`. `openwop.` is reserved.
|
|
@@ -59,6 +59,6 @@ An operation gated on a family or facet the host does not advertise MUST answer
|
|
|
59
59
|
|
|
60
60
|
## Codes by HTTP status
|
|
61
61
|
|
|
62
|
-
Every registered code, by HTTP status, is listed in [error-codes.md](../generated/error-codes.md), generated from `spec/v2/errors.json` (
|
|
62
|
+
Every registered code, by HTTP status, is listed in [error-codes.md](../generated/error-codes.md), generated from `spec/v2/errors.json` (125 codes).
|
|
63
63
|
|
|
64
64
|
*Sources: RFCs 0171, 0213, 0227, 0228.*
|
package/spec/v2/core/headers.md
CHANGED
|
@@ -13,13 +13,13 @@ Standard headers keep their standard names: `Idempotency-Key`, `ETag`, `If-None-
|
|
|
13
13
|
| Header | Operations | Meaning |
|
|
14
14
|
| --- | --- | --- |
|
|
15
15
|
| `Accept-Language` | 1 | BCP-47 preference list; authoritative for locale selection (i18n.md). A malformed value MUST NOT produce a 400. |
|
|
16
|
-
| `Idempotency-Key` |
|
|
16
|
+
| `Idempotency-Key` | 18 | Per-mutation idempotency token (`idempotency.md` Layer 1). The server caches `(tenantId, endpoint, key)` → response for ≥24h. A duplicate request returns the cached response with `OpenWOP-Idempotent-Replay: true`. |
|
|
17
17
|
| `If-None-Match` | 2 | Conditional request on the discovery document (capabilities.md §1) and the run snapshot (runs.md §Snapshot). A value that matches the current `ETag` (runs.md §Caching and encoding) MUST yield `304 Not Modified` with no body. The 304 carries `OpenWOP-Version` like every response (versioning.md §1.4). |
|
|
18
18
|
| `Last-Event-ID` | 1 | Resume from sequence after this ID. |
|
|
19
|
-
| `OpenWOP-Client-Version` |
|
|
19
|
+
| `OpenWOP-Client-Version` | 68 | The protocol version the client implements (versioning.md §1.5). Compared with `minClientVersion` on major.minor. A malformed value is treated as absent and MUST NOT produce a 400. Never selects a contract. |
|
|
20
20
|
| `OpenWOP-Dedup` | 1 | When set, the host's cross-host claim system rejects a duplicate `(tenantId, scopeId)` pair with `409 Conflict`. |
|
|
21
21
|
| `OpenWOP-Force-Engine-Version` | 1 | Test keys only. The server emits this run's events as if it ran the given engine version, which must be within `Capabilities.testing.forceEngineVersionRange`. Servers MUST reject it on production API keys with `403 force_engine_version_forbidden`. |
|
|
22
|
-
| `OpenWOP-Version` |
|
|
22
|
+
| `OpenWOP-Version` | 68 | Selects one of the host's listed major.minor versions. Absent, `/.well-known/openwop` uses `preferredVersion` and every other unversioned path is v2; an unlisted value is 406 protocol_version_unsupported. |
|
|
23
23
|
|
|
24
24
|
## Cross-origin preflight
|
|
25
25
|
|
|
@@ -36,9 +36,9 @@ A host that answers a CORS preflight for an operation by granting the requesting
|
|
|
36
36
|
| `ETag` | 3 | Standard HTTP validator (RFC 9110 §8.8.3). The obligation is per operation: MUST on the discovery document (capabilities.md §1), SHOULD on the run snapshot (runs.md §Snapshot), a content hash on a prompt template (getPromptTemplate); see each operation. |
|
|
37
37
|
| `Location` | 1 | Canonical URI of the new template. |
|
|
38
38
|
| `OpenWOP-Idempotent-Replay` | 1 | Set when the response was served from the idempotency cache. |
|
|
39
|
-
| `OpenWOP-Version` |
|
|
39
|
+
| `OpenWOP-Version` | 68 | The contract that produced this response. It MUST equal the one used. |
|
|
40
40
|
| `Retry-After` | 2 | Seconds until the active claim is stale-eligible. |
|
|
41
|
-
| `WWW-Authenticate` |
|
|
41
|
+
| `WWW-Authenticate` | 61 | A `Bearer` challenge. On a host with an oauth2 or oidc lane it carries `resource_metadata` and `error="invalid_token"`. Never sent on a non-disclosure 404. |
|
|
42
42
|
|
|
43
43
|
## Webhook delivery headers
|
|
44
44
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
## Why this exists
|
|
7
7
|
|
|
8
|
-
In v2 a security behavior is not an opt-in flag. This document
|
|
8
|
+
In v2 a security behavior is not an opt-in flag. This document maps each surface to the behavior it binds, its invariant and its witness.
|
|
9
9
|
|
|
10
10
|
## The rule
|
|
11
11
|
|
|
@@ -29,6 +29,7 @@ A security-load-bearing behavior is an obligation of the surface that needs it.
|
|
|
29
29
|
| an `oauth2` or `oidc` lane | protected-resource metadata and challenges ([identity.md §2.5](identity.md)) | witnessable-gated | `auth-challenge-no-oracle` |
|
|
30
30
|
| any outbound request | no inbound credential on an onward hop (§Onward hops) | seam-gated | `inbound-credential-no-passthrough` |
|
|
31
31
|
| `auditLogIntegrity` | a chained, checkpointed, verifiable audit log (§Audit-log integrity) | witnessable-gated | `audit-checkpoint-signed-over-root` |
|
|
32
|
+
| `agents.proposals` | inert drafts, byte-matched install | witnessable-gated | `proposal-inert-until-applied`, `proposal-no-resynthesis` |
|
|
32
33
|
|
|
33
34
|
### Auth lanes
|
|
34
35
|
|
|
@@ -65,7 +66,7 @@ The remaining `sandbox` facets name the bound each invariant already carries: `a
|
|
|
65
66
|
|
|
66
67
|
### Compensation
|
|
67
68
|
|
|
68
|
-
A host that advertises `compensation` MUST serve `GET /runs/{runId}/compensation` (`schemas/v2/compensation-projection.schema.json`), keyed on the node and attempt the operator family uses. The read projection and the operator action family are the canonical wire.
|
|
69
|
+
A host that advertises `compensation` MUST serve `GET /runs/{runId}/compensation` (`schemas/v2/compensation-projection.schema.json`), keyed on the node and attempt the operator family uses. The read projection and the operator action family are the canonical wire.
|
|
69
70
|
|
|
70
71
|
The facets bind the policy shape (`schemas/v2/compensation-policy.schema.json`):
|
|
71
72
|
|
package/spec/v2/errors.json
CHANGED
|
@@ -1424,6 +1424,51 @@
|
|
|
1424
1424
|
},
|
|
1425
1425
|
"since": "2.45",
|
|
1426
1426
|
"source": "spec/v2/core/conversation.md §multiPartyConversation; RFC 0239 §C"
|
|
1427
|
+
},
|
|
1428
|
+
{
|
|
1429
|
+
"code": "proposal_state_conflict",
|
|
1430
|
+
"meaning": "The proposal is terminal (applied, rejected or archived) and the action is not allowed; details.state and details.action name it.",
|
|
1431
|
+
"httpStatus": 409,
|
|
1432
|
+
"statusSource": "v2 decision",
|
|
1433
|
+
"retriable": false,
|
|
1434
|
+
"details": {
|
|
1435
|
+
"type": "object",
|
|
1436
|
+
"required": ["state", "action"],
|
|
1437
|
+
"properties": {
|
|
1438
|
+
"state": { "type": "string", "description": "The proposal's current state." },
|
|
1439
|
+
"action": { "type": "string", "description": "The refused action: revise, apply or reject." }
|
|
1440
|
+
},
|
|
1441
|
+
"additionalProperties": true
|
|
1442
|
+
},
|
|
1443
|
+
"since": "2.46",
|
|
1444
|
+
"source": "spec/v2/facets/agents.schema.json §proposals; RFC 0249"
|
|
1445
|
+
},
|
|
1446
|
+
{
|
|
1447
|
+
"code": "proposal_stale",
|
|
1448
|
+
"meaning": "The proposal changed since the caller read it: an apply's artifactDigest differs from the persisted artifact's, or a revise lost a concurrent update. Nothing was installed.",
|
|
1449
|
+
"httpStatus": 409,
|
|
1450
|
+
"statusSource": "v2 decision",
|
|
1451
|
+
"retriable": false,
|
|
1452
|
+
"details": null,
|
|
1453
|
+
"since": "2.46",
|
|
1454
|
+
"source": "spec/v2/facets/agents.schema.json §proposals; RFC 0249"
|
|
1455
|
+
},
|
|
1456
|
+
{
|
|
1457
|
+
"code": "proposal_install_conflict",
|
|
1458
|
+
"meaning": "The target store refused the install; details.reason is version-not-greater or read-only. Nothing was installed and the proposal's state is unchanged.",
|
|
1459
|
+
"httpStatus": 409,
|
|
1460
|
+
"statusSource": "v2 decision",
|
|
1461
|
+
"retriable": false,
|
|
1462
|
+
"details": {
|
|
1463
|
+
"type": "object",
|
|
1464
|
+
"required": ["reason"],
|
|
1465
|
+
"properties": {
|
|
1466
|
+
"reason": { "type": "string", "enum": ["version-not-greater", "read-only"], "description": "Why the store refused (RFC 0249 §D)." }
|
|
1467
|
+
},
|
|
1468
|
+
"additionalProperties": true
|
|
1469
|
+
},
|
|
1470
|
+
"since": "2.46",
|
|
1471
|
+
"source": "spec/v2/facets/agents.schema.json §proposals; RFC 0249"
|
|
1427
1472
|
}
|
|
1428
1473
|
]
|
|
1429
1474
|
}
|
|
@@ -368,7 +368,7 @@
|
|
|
368
368
|
},
|
|
369
369
|
"proposals": {
|
|
370
370
|
"type": "object",
|
|
371
|
-
"description": "RFC 0096 (`Active`). Reviewable learning — the host synthesizes reusable artifacts (skills/packs/templates/automations) from run/tool traces as INERT, reviewable drafts that MUST NOT influence the resolution, planning, or execution of any run until an authorized principal activates them.
|
|
371
|
+
"description": "RFC 0096 (`Active`), operations by RFC 0249. Reviewable learning — the host synthesizes reusable artifacts (skills/packs/templates/automations) from run/tool traces as INERT, reviewable drafts that MUST NOT influence the resolution, planning, or execution of any run until an authorized principal activates them. The surface is the seven `proposals` operations (`listProposals`, `getProposal`, `submitProposal`, `reviseProposal`, `applyProposal`, `rejectProposal`, `archiveProposal`; scopes `proposals:read`, `proposals:write`, `proposals:apply`); a host that omits this block answers each as `errors.md` §Unadvertised operations requires. A proposal another tenant owns MUST be answered exactly as an unknown id. `applied`, `rejected` and `archived` are terminal: revise, apply or reject on one, and archive on `applied` or `archived`, is refused `409 proposal_state_conflict`. A host advertising this emits the content-free `proposal.created` / `proposal.activated` events. Activation is delegated to RFC 0051 approval-gate (apply opens a gate run that suspends on an `approval` interrupt) or RFC 0049 RBAC (`proposals:apply`) — no new authorization path. On `apply` the installed artifact MUST byte-match the last-persisted `artifact` (no silent re-synthesis); `activation.installedArtifact` names the read that shows it. The redaction-safety of `rationale` and `provenance.sourceRunIds` and the lifecycle are in `proposal.schema.json`.",
|
|
372
372
|
"additionalProperties": false,
|
|
373
373
|
"required": [
|
|
374
374
|
"artifactKinds",
|
|
@@ -401,6 +401,25 @@
|
|
|
401
401
|
"direct-rbac"
|
|
402
402
|
],
|
|
403
403
|
"description": "`approval-gate`: `apply` MUST drive an RFC 0051 gate (role/scope/quorum, audited override) and MUST NOT install unless granted/overridden. `direct-rbac`: `apply` requires only the RFC 0049 scope the host advertises for activation. An `overridden` gate MUST be audited."
|
|
404
|
+
},
|
|
405
|
+
"clientDrafts": {
|
|
406
|
+
"type": "boolean",
|
|
407
|
+
"default": false,
|
|
408
|
+
"description": "RFC 0249 §B. When `true`, `submitProposal` accepts a client-authored draft. A submitted draft MUST be held to every rule a synthesized one is, inertness first, with `provenance.sourceRunIds: []`. Absent or `false`, `submitProposal` answers `404 not_found`."
|
|
409
|
+
},
|
|
410
|
+
"readback": {
|
|
411
|
+
"type": "array",
|
|
412
|
+
"uniqueItems": true,
|
|
413
|
+
"items": {
|
|
414
|
+
"type": "string",
|
|
415
|
+
"enum": [
|
|
416
|
+
"agent-pack",
|
|
417
|
+
"workflow-chain-pack",
|
|
418
|
+
"prompt-template",
|
|
419
|
+
"automation"
|
|
420
|
+
]
|
|
421
|
+
},
|
|
422
|
+
"description": "RFC 0249 §D. The kinds whose installed artifact resolves through `activation.installedArtifact`; a subset of `artifactKinds`. For `prompt-template` the read is `getPromptTemplate`, only `meta` is host-owned, and while a proposal is unapplied `getPromptTemplate` / `listPromptTemplates` MUST NOT serve a template carrying its `(templateId, version)` and `POST /prompts:render` naming it MUST fail as for an unknown template. Install follows the prompts write in the applying tenant, and a refused install is `409 proposal_install_conflict`. A kind proposed but absent here has no outside read-back: its RFC 0096 rules bind but are not checkable from the wire (`workflow-chain-pack`, `agent-pack` and `automation` have no read-back at v2 today)."
|
|
404
423
|
}
|
|
405
424
|
}
|
|
406
425
|
},
|