@openwop/openwop-conformance 1.163.0 → 2.0.0-rc.1
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/README.md +11 -2
- package/dist/cli.js +262 -14
- package/dist/lib/certification-bundle-v3.js +142 -0
- package/dist/lib/paths.js +25 -3
- package/dist/lib/requirement-ids.js +57 -4
- package/dist/lib/requirement-ledger.js +1 -0
- package/dist/lib/scenario-disposition.js +6 -1
- package/dist/lib/spec-coherence.js +13 -32
- package/dist/spec-artifacts.lock.json +5 -0
- package/package.json +11 -33
- package/requirements.json +22892 -11701
- package/scenario-majors.json +1493 -0
- package/schemas/CORPUS-STAMP.json +137 -5
- package/src/cli.ts +236 -19
- package/src/global-setup.ts +3 -2
- package/src/lib/certification-bundle-v3.ts +175 -0
- package/src/lib/corpus-stamp.ts +29 -1
- package/src/lib/driver.ts +9 -1
- package/src/lib/era2-seed.ts +197 -0
- package/src/lib/paths.ts +25 -3
- package/src/lib/requirement-ids.ts +54 -4
- package/src/lib/requirement-ledger.ts +7 -1
- package/src/lib/scenario-disposition.ts +6 -1
- package/src/lib/seams.ts +45 -0
- package/src/lib/spec-coherence.ts +15 -32
- package/src/lib/v2.ts +62 -0
- package/src/scenarios/a2a-1-0-agent-card.test.ts +17 -16
- package/src/scenarios/a2a-1-0-task-roundtrip.test.ts +11 -10
- package/src/scenarios/a2a-card-runtime-consistency.test.ts +18 -17
- package/src/scenarios/a2a-peer-authority.test.ts +7 -6
- package/src/scenarios/a2a-task-roundtrip.test.ts +30 -29
- package/src/scenarios/a2a-version-negotiation.test.ts +16 -14
- package/src/scenarios/a2ui-surface-degrades.test.ts +5 -3
- package/src/scenarios/a2ui-surface-delta-transport.test.ts +35 -33
- package/src/scenarios/a2ui-surface-replay.test.ts +6 -4
- package/src/scenarios/a2ui-surface-shape.test.ts +11 -10
- package/src/scenarios/a2ui-surface-version-refusal.test.ts +6 -4
- package/src/scenarios/a2ui-untrusted-blocks-approval.test.ts +5 -3
- package/src/scenarios/agent-capability-degraded-projection.test.ts +12 -11
- package/src/scenarios/agent-channel-dispatch.test.ts +18 -16
- package/src/scenarios/agent-deployment-lifecycle.test.ts +20 -19
- package/src/scenarios/agent-deployment-shape.test.ts +22 -24
- package/src/scenarios/agent-eval-run.test.ts +19 -18
- package/src/scenarios/agent-eval-suite-shape.test.ts +20 -22
- package/src/scenarios/agent-live-allowlist-enforced.test.ts +6 -5
- package/src/scenarios/agent-live-invocation-bracket.test.ts +13 -12
- package/src/scenarios/agent-live-runtime-shape.test.ts +10 -12
- package/src/scenarios/agent-live-structured-output.test.ts +7 -6
- package/src/scenarios/agent-loop-iteration-monotonic.test.ts +3 -3
- package/src/scenarios/agent-loop-stateful-resume.test.ts +2 -2
- package/src/scenarios/agent-loop-version5-shape.test.ts +4 -4
- package/src/scenarios/agent-loop-workspace-snapshot.test.ts +3 -3
- package/src/scenarios/agent-manifest-role-profile.test.ts +9 -9
- package/src/scenarios/agent-manifest-runtime.test.ts +13 -12
- package/src/scenarios/agent-org-chart-scoping.test.ts +14 -13
- package/src/scenarios/agent-org-chart-shape.test.ts +11 -13
- package/src/scenarios/agent-platform-aggregate-evidence.test.ts +5 -4
- package/src/scenarios/agent-platform-profile.test.ts +18 -19
- package/src/scenarios/agent-requires-capabilities-shape.test.ts +4 -4
- package/src/scenarios/agent-roster-attribution.test.ts +18 -17
- package/src/scenarios/agent-roster-shape.test.ts +17 -19
- package/src/scenarios/agent-verifier-shape.test.ts +11 -11
- package/src/scenarios/agentConfidenceEscalation.test.ts +2 -1
- package/src/scenarios/agentMemoryCrossTenantIsolation.test.ts +6 -5
- package/src/scenarios/agentMemoryRedactionContract.test.ts +2 -1
- package/src/scenarios/agentMemoryRoundTrip.test.ts +2 -1
- package/src/scenarios/agentMemoryTtlExpiry.test.ts +4 -3
- package/src/scenarios/agentMessageReducer.test.ts +2 -1
- package/src/scenarios/agentMetadata.test.ts +2 -1
- package/src/scenarios/agentPackCatalog.test.ts +23 -21
- package/src/scenarios/agentPackExport.test.ts +4 -2
- package/src/scenarios/agentPackHandoffSchemaValidation.test.ts +5 -4
- package/src/scenarios/agentPackInstall.test.ts +4 -2
- package/src/scenarios/agentPackProvenance.test.ts +2 -1
- package/src/scenarios/agentReasoningEvents.test.ts +3 -2
- package/src/scenarios/agentReasoningStreaming.test.ts +11 -10
- package/src/scenarios/agents-run-tool-allowlist.test.ts +14 -12
- package/src/scenarios/ai-envelope-shape.test.ts +31 -29
- package/src/scenarios/aiEnvelope.capBreached.test.ts +26 -24
- package/src/scenarios/aiEnvelope.contractRefusal.test.ts +36 -34
- package/src/scenarios/aiEnvelope.correlationReplay.test.ts +17 -15
- package/src/scenarios/aiEnvelope.redaction.test.ts +22 -20
- package/src/scenarios/aiEnvelope.schemaDrift.test.ts +18 -16
- package/src/scenarios/aiEnvelope.trustBoundaryPropagation.test.ts +38 -36
- package/src/scenarios/aiEnvelope.universalKinds.test.ts +31 -29
- package/src/scenarios/aiproviders-input-shape.test.ts +5 -5
- package/src/scenarios/aiproviders-realtimevoice-shape.test.ts +14 -16
- package/src/scenarios/aiproviders-selfhosted-honesty.test.ts +6 -4
- package/src/scenarios/aiproviders-selfhosted-shape.test.ts +15 -17
- package/src/scenarios/aiproviders-speechsynth-shape.test.ts +6 -8
- package/src/scenarios/aiproviders-subscription-scope.test.ts +7 -8
- package/src/scenarios/anonymous-actor-audit-opaque.test.ts +9 -8
- package/src/scenarios/anonymous-actor-default-deny.test.ts +10 -9
- package/src/scenarios/anonymous-actor-egress-guarded.test.ts +6 -5
- package/src/scenarios/anonymous-actor-no-secret-reach.test.ts +7 -6
- package/src/scenarios/anonymous-actor-shape.test.ts +17 -19
- package/src/scenarios/anonymous-actor-write-gated.test.ts +9 -8
- package/src/scenarios/append-ordering.test.ts +7 -5
- package/src/scenarios/approval-gate-events.test.ts +4 -3
- package/src/scenarios/approval-gate-flow.test.ts +4 -3
- package/src/scenarios/approval-payload.test.ts +5 -4
- package/src/scenarios/artifact-auth.test.ts +7 -6
- package/src/scenarios/artifact-type-pack-install.test.ts +6 -6
- package/src/scenarios/artifact-type-pack-manifest-validation.test.ts +9 -8
- package/src/scenarios/artifact-type-registration-source.test.ts +20 -20
- package/src/scenarios/artifact-type-store-emission.test.ts +15 -18
- package/src/scenarios/artifact-type-store-without-render.test.ts +4 -4
- package/src/scenarios/audit-log-integrity.test.ts +8 -6
- package/src/scenarios/auth-api-key-rotation.test.ts +11 -9
- package/src/scenarios/auth-mtls.test.ts +22 -20
- package/src/scenarios/auth-oauth2-client-credentials.test.ts +16 -14
- package/src/scenarios/auth-oidc-user-bearer.test.ts +26 -24
- package/src/scenarios/auth-saml-profile.test.ts +14 -12
- package/src/scenarios/auth-scim-profile.test.ts +3 -2
- package/src/scenarios/auth-subject-link-key-class.test.ts +8 -7
- package/src/scenarios/auth-subject-link.test.ts +11 -10
- package/src/scenarios/auth.test.ts +5 -4
- package/src/scenarios/authorization-fail-closed.test.ts +3 -2
- package/src/scenarios/authorization-roles-shape.test.ts +9 -7
- package/src/scenarios/blob-cross-tenant-isolation.test.ts +8 -6
- package/src/scenarios/blob-presign-expiry.test.ts +12 -10
- package/src/scenarios/blob-roundtrip.test.ts +0 -0
- package/src/scenarios/budget-enforcement.test.ts +15 -14
- package/src/scenarios/budget-policy-shape.test.ts +18 -19
- package/src/scenarios/bulk-cancel.test.ts +9 -8
- package/src/scenarios/byok-auth-modes.test.ts +13 -14
- package/src/scenarios/byok-roundtrip.test.ts +12 -10
- package/src/scenarios/cache-cross-tenant-isolation.test.ts +8 -6
- package/src/scenarios/cache-ttl-expiry.test.ts +7 -5
- package/src/scenarios/callai-multimodal.test.ts +5 -3
- package/src/scenarios/cancellation.test.ts +6 -5
- package/src/scenarios/cap-breach.test.ts +15 -14
- package/src/scenarios/capability-arm-witness.test.ts +5 -3
- package/src/scenarios/certification-bundle-non-vacuous.test.ts +20 -19
- package/src/scenarios/certification-bundle-redaction.test.ts +11 -10
- package/src/scenarios/certification-bundle-v2.test.ts +11 -10
- package/src/scenarios/chain-compensation-expansion.test.ts +14 -13
- package/src/scenarios/chain-produced-var-roundtrip.test.ts +13 -14
- package/src/scenarios/chain-subchain-cycle-rejected.test.ts +9 -10
- package/src/scenarios/chain-subchain-fanout.test.ts +8 -9
- package/src/scenarios/chain-subchain-sibling.test.ts +14 -16
- package/src/scenarios/channel-presence-behavioral.test.ts +9 -7
- package/src/scenarios/channel-presence-shape.test.ts +11 -12
- package/src/scenarios/channel-ttl.test.ts +6 -5
- package/src/scenarios/chat-card-pack-execution.test.ts +4 -4
- package/src/scenarios/chat-card-pack-manifest-validation.test.ts +9 -8
- package/src/scenarios/commitment-fired.test.ts +6 -5
- package/src/scenarios/compensation-behavior.test.ts +24 -23
- package/src/scenarios/compensation-recovery.test.ts +28 -27
- package/src/scenarios/configurable-schema.test.ts +8 -6
- package/src/scenarios/conformance-advertised-seam-required.test.ts +6 -5
- package/src/scenarios/conformance-execution-witness.test.ts +9 -8
- package/src/scenarios/connection-pack-apihosts.test.ts +19 -17
- package/src/scenarios/connection-pack-manifest-valid.test.ts +12 -11
- package/src/scenarios/connection-pack-no-credential-material.test.ts +8 -6
- package/src/scenarios/connection-pack-reach-exclusive.test.ts +5 -4
- package/src/scenarios/connection-pack-write-reconsent.test.ts +6 -4
- package/src/scenarios/connection-provider-resolution.test.ts +18 -16
- package/src/scenarios/connector-manifest-validity.test.ts +8 -7
- package/src/scenarios/context-budget-transcript-bound.test.ts +17 -15
- package/src/scenarios/context-summarization-replay.test.ts +14 -12
- package/src/scenarios/contract-provenance.test.ts +18 -18
- package/src/scenarios/conversation-turn-model-provenance-shape.test.ts +14 -15
- package/src/scenarios/conversationCapabilityNegotiation.test.ts +2 -1
- package/src/scenarios/conversationLifecycle.test.ts +2 -1
- package/src/scenarios/conversationReplayDeterminism.test.ts +4 -2
- package/src/scenarios/conversationVsLegacySuspend.test.ts +2 -1
- package/src/scenarios/core-standard-profile.test.ts +8 -9
- package/src/scenarios/cost-attribution.test.ts +23 -21
- package/src/scenarios/credential-payload-redaction.test.ts +4 -3
- package/src/scenarios/credentials-capability-shape.test.ts +5 -4
- package/src/scenarios/cross-engine-append-behavior.test.ts +11 -10
- package/src/scenarios/cross-engine-append-ordering.test.ts +4 -3
- package/src/scenarios/cross-host-ancestry-endpoint.test.ts +11 -10
- package/src/scenarios/cross-host-causation-shape.test.ts +7 -6
- package/src/scenarios/cross-workspace-isolation.test.ts +4 -3
- package/src/scenarios/data-residency-admission.test.ts +15 -14
- package/src/scenarios/deadletter-capability-shape.test.ts +6 -4
- package/src/scenarios/deadletter-retry-exhaustion.test.ts +4 -3
- package/src/scenarios/debug-bundle-truncation.test.ts +9 -7
- package/src/scenarios/debugBundle.test.ts +25 -23
- package/src/scenarios/discovery-families-view.test.ts +5 -4
- package/src/scenarios/discovery.test.ts +30 -29
- package/src/scenarios/dispatch-cross-worker-handoff.test.ts +10 -8
- package/src/scenarios/dispatch-fanout-parallel.test.ts +24 -22
- package/src/scenarios/dispatch-input-mapping.test.ts +12 -10
- package/src/scenarios/dispatch-output-mapping.test.ts +9 -7
- package/src/scenarios/dispatch-per-item-input.test.ts +22 -20
- package/src/scenarios/dispatchLoop.test.ts +3 -2
- package/src/scenarios/distillation-index-roundtrip.test.ts +3 -3
- package/src/scenarios/distillation-secret-carryforward.test.ts +2 -2
- package/src/scenarios/distillation-shape.test.ts +4 -4
- package/src/scenarios/distillation-stable-archive.test.ts +6 -6
- package/src/scenarios/distillation-token-budget.test.ts +5 -5
- package/src/scenarios/durability-poison-exhaustion.test.ts +7 -6
- package/src/scenarios/egress-audience-binding.test.ts +11 -10
- package/src/scenarios/egress-decision-content-free.test.ts +6 -5
- package/src/scenarios/egress-provenance-shape.test.ts +17 -18
- package/src/scenarios/envelope-completion-distinguishes-truncation.test.ts +27 -25
- package/src/scenarios/envelope-nl-to-format-engaged.test.ts +19 -17
- package/src/scenarios/envelope-reasoning-secret-redaction.test.ts +28 -26
- package/src/scenarios/envelope-reasoning-shape.test.ts +19 -17
- package/src/scenarios/envelope-recovery-applied.test.ts +24 -22
- package/src/scenarios/envelope-refusal-shape.test.ts +31 -29
- package/src/scenarios/envelope-rendering-hint.test.ts +5 -4
- package/src/scenarios/envelope-retry-attempted.test.ts +33 -31
- package/src/scenarios/envelope-retry-exhausted.test.ts +22 -20
- package/src/scenarios/envelope-tier-one-subset-static.test.ts +9 -7
- package/src/scenarios/envelope-truncated.test.ts +19 -17
- package/src/scenarios/envelope-truncation-cap-exhaustion.test.ts +19 -17
- package/src/scenarios/envelope-variant-discriminator-static.test.ts +4 -3
- package/src/scenarios/errors.test.ts +20 -19
- package/src/scenarios/eventOrdering.test.ts +16 -14
- package/src/scenarios/exec-not-protocol-tier.test.ts +5 -7
- package/src/scenarios/experimental-tier-shape.test.ts +17 -15
- package/src/scenarios/export-bundle-portability.test.ts +17 -17
- package/src/scenarios/failure-path.test.ts +7 -6
- package/src/scenarios/feedback-capability-shape.test.ts +4 -3
- package/src/scenarios/feedback-correction-redaction.test.ts +2 -1
- package/src/scenarios/feedback-cross-tenant-isolation.test.ts +2 -1
- package/src/scenarios/feedback-fork-not-copied.test.ts +3 -2
- package/src/scenarios/feedback-on-terminal-run.test.ts +3 -2
- package/src/scenarios/feedback-record-and-list.test.ts +2 -1
- package/src/scenarios/feedback-unsupported-501.test.ts +2 -1
- package/src/scenarios/fixtures-gating.test.ts +29 -28
- package/src/scenarios/fixtures-valid.test.ts +16 -15
- package/src/scenarios/form-content-instantiation.test.ts +15 -14
- package/src/scenarios/frontend-plugin-packs.test.ts +29 -27
- package/src/scenarios/fs-path-traversal.test.ts +14 -12
- package/src/scenarios/goal-standing-continuation.test.ts +21 -21
- package/src/scenarios/grpc-transport.test.ts +9 -7
- package/src/scenarios/heartbeat-capability-shape.test.ts +3 -3
- package/src/scenarios/heartbeat-fires-once-per-tick.test.ts +2 -2
- package/src/scenarios/heartbeat-idempotent-no-spam.test.ts +3 -3
- package/src/scenarios/heartbeat-runtime-bound.test.ts +2 -2
- package/src/scenarios/highConcurrency.test.ts +14 -13
- package/src/scenarios/host-callback-declaration.test.ts +8 -7
- package/src/scenarios/http-client-ssrf.test.ts +7 -5
- package/src/scenarios/i18n-negotiation.test.ts +14 -12
- package/src/scenarios/idempotency-concurrent-claim.test.ts +14 -13
- package/src/scenarios/idempotency-key-determinism.test.ts +20 -18
- package/src/scenarios/idempotency.test.ts +8 -7
- package/src/scenarios/idempotencyRetry.test.ts +13 -11
- package/src/scenarios/identity-owner-shape.test.ts +6 -5
- package/src/scenarios/identity-passthrough.test.ts +4 -3
- package/src/scenarios/interrupt-approval.test.ts +6 -5
- package/src/scenarios/interrupt-approver-routing.test.ts +15 -15
- package/src/scenarios/interrupt-auth-required-resume.test.ts +5 -3
- package/src/scenarios/interrupt-clarification.test.ts +4 -3
- package/src/scenarios/interrupt-external-event-correlation.test.ts +6 -5
- package/src/scenarios/interrupt-parent-child-cascade.test.ts +4 -3
- package/src/scenarios/interrupt-quorum-resolution.test.ts +5 -4
- package/src/scenarios/interrupt-token-matrix.test.ts +8 -6
- package/src/scenarios/interruptRace.test.ts +12 -10
- package/src/scenarios/kv-atomic-increment.test.ts +11 -9
- package/src/scenarios/kv-cas.test.ts +14 -12
- package/src/scenarios/kv-cross-tenant-isolation.test.ts +12 -10
- package/src/scenarios/kv-ttl-expiry.test.ts +7 -5
- package/src/scenarios/localized-content-delivery.test.ts +24 -26
- package/src/scenarios/maliciousManifest.test.ts +10 -8
- package/src/scenarios/mcp-2026-07-28-discover.test.ts +15 -14
- package/src/scenarios/mcp-cache-tenant-scope.test.ts +6 -5
- package/src/scenarios/mcp-current-auth-boundary.test.ts +7 -6
- package/src/scenarios/mcp-discoverability.test.ts +9 -7
- package/src/scenarios/mcp-extension-opacity.test.ts +7 -6
- package/src/scenarios/mcp-mrtr-roundtrip.test.ts +18 -17
- package/src/scenarios/mcp-server-elicitation-bridge.test.ts +13 -12
- package/src/scenarios/mcp-server-prompt-roundtrip.test.ts +11 -10
- package/src/scenarios/mcp-server-resource-roundtrip.test.ts +11 -10
- package/src/scenarios/mcp-server-sampling-bridge.test.ts +12 -11
- package/src/scenarios/mcp-server-tool-roundtrip.test.ts +14 -13
- package/src/scenarios/mcp-server-untrusted-args.test.ts +14 -13
- package/src/scenarios/mcp-stateless-request.test.ts +11 -10
- package/src/scenarios/mcp-tool-roundtrip.test.ts +4 -3
- package/src/scenarios/mcp-toolcall-redaction.test.ts +4 -3
- package/src/scenarios/mcp-version-negotiation.test.ts +15 -14
- package/src/scenarios/media-url-inline-cap.test.ts +21 -19
- package/src/scenarios/memory-attribution-emits-on-write.test.ts +5 -5
- package/src/scenarios/memory-attribution-no-content.test.ts +4 -4
- package/src/scenarios/memory-attribution-replay-stable.test.ts +4 -3
- package/src/scenarios/memory-attribution-shape.test.ts +4 -3
- package/src/scenarios/memory-attribution-tenant-scoped.test.ts +3 -3
- package/src/scenarios/memory-capability-model-shape.test.ts +14 -15
- package/src/scenarios/memory-compaction-event-emitted.test.ts +7 -6
- package/src/scenarios/memory-compaction-provenance-tag.test.ts +3 -2
- package/src/scenarios/memory-compaction-sr1-carry-forward.test.ts +7 -6
- package/src/scenarios/memory-consolidation-idempotent.test.ts +5 -4
- package/src/scenarios/memory-consolidation-shape.test.ts +9 -11
- package/src/scenarios/memory-degraded-projection.test.ts +10 -9
- package/src/scenarios/memory-injection-budget.test.ts +15 -14
- package/src/scenarios/metric-emission.test.ts +4 -3
- package/src/scenarios/model-capability-insufficient.test.ts +19 -17
- package/src/scenarios/model-capability-substituted.test.ts +20 -18
- package/src/scenarios/multi-agent-confidence-escalation.test.ts +12 -11
- package/src/scenarios/multi-agent-handoff-state-machine.test.ts +10 -9
- package/src/scenarios/multi-agent-memory-lifecycle.test.ts +11 -10
- package/src/scenarios/multi-node-ordering.test.ts +4 -3
- package/src/scenarios/multi-party-conversation-behavioral.test.ts +6 -6
- package/src/scenarios/multi-party-conversation-shape.test.ts +21 -23
- package/src/scenarios/multi-region-idempotency-behavior.test.ts +16 -15
- package/src/scenarios/multi-region-idempotency.test.ts +6 -5
- package/src/scenarios/node-failed-payload-shape.test.ts +5 -4
- package/src/scenarios/node-module-required-capabilities-shape.test.ts +10 -8
- package/src/scenarios/oauth-authorization-code-roundtrip.test.ts +5 -4
- package/src/scenarios/oauth-capability-shape.test.ts +5 -4
- package/src/scenarios/oauth-connector-redaction.test.ts +4 -3
- package/src/scenarios/openapi-resolved-paths.test.ts +6 -5
- package/src/scenarios/orchestratorConservativePath.test.ts +2 -1
- package/src/scenarios/orchestratorDispatch.test.ts +2 -1
- package/src/scenarios/orchestratorTermination.test.ts +2 -1
- package/src/scenarios/org-position-no-authority-escalation.test.ts +2 -2
- package/src/scenarios/otel-collector-canary-inspection.test.ts +8 -7
- package/src/scenarios/otel-emission-grpc.test.ts +3 -2
- package/src/scenarios/otel-emission.test.ts +6 -5
- package/src/scenarios/otel-trace-propagation-subworkflow.test.ts +7 -6
- package/src/scenarios/otel-trace-propagation.test.ts +2 -1
- package/src/scenarios/owner-subject-echo.test.ts +13 -12
- package/src/scenarios/owner-subject-shape.test.ts +11 -10
- package/src/scenarios/pack-manifest-extension-opacity.test.ts +8 -8
- package/src/scenarios/pack-registry-isolation.test.ts +4 -3
- package/src/scenarios/pack-registry-publish.test.ts +65 -63
- package/src/scenarios/pack-registry.test.ts +38 -36
- package/src/scenarios/pause-resume.test.ts +18 -16
- package/src/scenarios/policies.test.ts +20 -18
- package/src/scenarios/production-backpressure.test.ts +18 -16
- package/src/scenarios/production-retention-expiry.test.ts +8 -6
- package/src/scenarios/profile-discovery-core-alias.test.ts +13 -11
- package/src/scenarios/profileDerivation.test.ts +34 -33
- package/src/scenarios/prompt-all-four-kinds-events.test.ts +11 -9
- package/src/scenarios/prompt-composed-secret-redaction.test.ts +11 -9
- package/src/scenarios/prompt-composed-trust-marker.test.ts +10 -8
- package/src/scenarios/prompt-end-to-end-events.test.ts +17 -15
- package/src/scenarios/prompt-list-and-fetch.test.ts +16 -14
- package/src/scenarios/prompt-mutable-lifecycle.test.ts +13 -11
- package/src/scenarios/prompt-mutation-workspace-membership-enforced.test.ts +6 -4
- package/src/scenarios/prompt-pack-install.test.ts +14 -12
- package/src/scenarios/prompt-prefix-cache.test.ts +19 -17
- package/src/scenarios/prompt-read-workspace-membership-enforced.test.ts +11 -9
- package/src/scenarios/prompt-render-deterministic.test.ts +19 -17
- package/src/scenarios/prompt-resolution-chain-agent-intrinsic.test.ts +7 -5
- package/src/scenarios/prompt-resolution-chain-event.test.ts +12 -10
- package/src/scenarios/prompt-resolution-chain-fallback-cascade.test.ts +10 -8
- package/src/scenarios/prompt-resolution-chain-node-wins.test.ts +8 -6
- package/src/scenarios/prompt-template-shape.test.ts +30 -28
- package/src/scenarios/proposal-reviewable-learning.test.ts +19 -19
- package/src/scenarios/protocol-versions-array.test.ts +10 -9
- package/src/scenarios/provider-usage.test.ts +17 -15
- package/src/scenarios/providerPolicyEnforcement.test.ts +16 -14
- package/src/scenarios/purpose-propagation.test.ts +23 -21
- package/src/scenarios/queue-ack-nack-dlq.test.ts +12 -10
- package/src/scenarios/queue-cross-tenant-isolation.test.ts +8 -6
- package/src/scenarios/queue-publish-consume-roundtrip.test.ts +10 -8
- package/src/scenarios/rate-limit-envelope.test.ts +6 -5
- package/src/scenarios/redaction.test.ts +13 -11
- package/src/scenarios/redactionAdversarial.test.ts +11 -9
- package/src/scenarios/registry-public.test.ts +12 -11
- package/src/scenarios/replay-divergence-at-refusal.test.ts +16 -15
- package/src/scenarios/replay-fanout-suppression.test.ts +16 -15
- package/src/scenarios/replay-fork-arbitrary.test.ts +24 -23
- package/src/scenarios/replay-fork.test.ts +20 -19
- package/src/scenarios/replay-llm-cache-key-portable.test.ts +11 -9
- package/src/scenarios/replay-llm-cache-key.test.ts +22 -21
- package/src/scenarios/replay-observable-sequence-determinism.test.ts +4 -3
- package/src/scenarios/replay-retention-expiry.test.ts +11 -9
- package/src/scenarios/replay-side-effect-suppression.test.ts +21 -19
- package/src/scenarios/replayDeterminism.test.ts +13 -12
- package/src/scenarios/requirement-ledger.test.ts +15 -14
- package/src/scenarios/restart-during-run.test.ts +3 -2
- package/src/scenarios/route-coverage.test.ts +20 -19
- package/src/scenarios/run-diff.test.ts +22 -20
- package/src/scenarios/run-execution-bounds-shape.test.ts +14 -12
- package/src/scenarios/run-transport-economy.test.ts +13 -11
- package/src/scenarios/runner-ledger.test.ts +17 -16
- package/src/scenarios/runs-lifecycle.test.ts +7 -6
- package/src/scenarios/runtime-capabilities.test.ts +12 -10
- package/src/scenarios/runtime-requires-install-gate.test.ts +8 -8
- package/src/scenarios/runtime-requires-shape.test.ts +7 -6
- package/src/scenarios/safefetch-behavior.test.ts +22 -21
- package/src/scenarios/safefetch-live-audit.test.ts +14 -13
- package/src/scenarios/sandbox-memory-cap.test.ts +2 -1
- package/src/scenarios/sandbox-mvp-behavior.test.ts +24 -23
- package/src/scenarios/sandbox-no-host-fs-escape.test.ts +3 -2
- package/src/scenarios/sandbox-timeout-cap.test.ts +2 -1
- package/src/scenarios/sandbox-wasm-isolation.test.ts +14 -15
- package/src/scenarios/sandbox-wasm-timeout.test.ts +5 -6
- package/src/scenarios/scheduling-capability-shape.test.ts +8 -6
- package/src/scenarios/scheduling-cron-fires-once.test.ts +8 -6
- package/src/scenarios/search-bm25-roundtrip.test.ts +8 -6
- package/src/scenarios/secret-leakage-otel-attribute.test.ts +22 -20
- package/src/scenarios/self-hosted-runner.test.ts +26 -24
- package/src/scenarios/semantic-digest-vectors.test.ts +8 -7
- package/src/scenarios/speech-synthesis-roundtrip.test.ts +9 -7
- package/src/scenarios/speech-synthesis-unadvertised.test.ts +5 -3
- package/src/scenarios/sql-injection-rejection.test.ts +8 -6
- package/src/scenarios/sql-transaction-atomicity.test.ts +10 -8
- package/src/scenarios/staleClaim.test.ts +5 -4
- package/src/scenarios/stream-modes-buffer.test.ts +8 -7
- package/src/scenarios/stream-modes-mixed.test.ts +10 -9
- package/src/scenarios/stream-modes.test.ts +12 -11
- package/src/scenarios/stream-subscribe-from-beginning.test.ts +11 -9
- package/src/scenarios/stream-text-fixture.test.ts +14 -13
- package/src/scenarios/streamReconnect.test.ts +13 -11
- package/src/scenarios/strict-behavior-gate.test.ts +9 -8
- package/src/scenarios/subrun-approval-fail-closed.test.ts +2 -2
- package/src/scenarios/subrun-approval-gate.test.ts +3 -3
- package/src/scenarios/subrun-attestation-shape.test.ts +2 -2
- package/src/scenarios/subrun-checksum-stable.test.ts +4 -4
- package/src/scenarios/subworkflow-input-mapping.test.ts +16 -14
- package/src/scenarios/subworkflow.test.ts +10 -9
- package/src/scenarios/table-cross-tenant-isolation.test.ts +8 -6
- package/src/scenarios/table-cursor-pagination.test.ts +8 -6
- package/src/scenarios/table-schema-enforcement.test.ts +7 -5
- package/src/scenarios/test-seam-unauthenticated.test.ts +2 -2
- package/src/scenarios/tool-catalog-compact-projection.test.ts +10 -8
- package/src/scenarios/tool-catalog-projection.test.ts +11 -9
- package/src/scenarios/tool-descriptor-shape.test.ts +14 -15
- package/src/scenarios/tool-hooks-authorization-fail-closed.test.ts +3 -3
- package/src/scenarios/tool-hooks-content-free.test.ts +4 -4
- package/src/scenarios/tool-hooks-failure-honesty.test.ts +4 -4
- package/src/scenarios/tool-hooks-rate-limit.test.ts +2 -2
- package/src/scenarios/tool-hooks-secret-redaction.test.ts +2 -2
- package/src/scenarios/tool-hooks-shape.test.ts +3 -3
- package/src/scenarios/tool-session-lifecycle.test.ts +14 -13
- package/src/scenarios/trigger-bridge-delivery.test.ts +14 -14
- package/src/scenarios/trigger-bridge-shape.test.ts +19 -20
- package/src/scenarios/trigger-ingestion.test.ts +19 -17
- package/src/scenarios/trigger-stream-cdc-sources.test.ts +16 -14
- package/src/scenarios/v2-approver-enforced.test.ts +97 -0
- package/src/scenarios/v2-assurance-downgrade-audited.test.ts +75 -0
- package/src/scenarios/v2-bundle-v3-signed.test.ts +96 -0
- package/src/scenarios/v2-capabilities-root-closed.test.ts +63 -0
- package/src/scenarios/v2-capability-record-shape.test.ts +104 -0
- package/src/scenarios/v2-chain-pin-exact.test.ts +118 -0
- package/src/scenarios/v2-coherence-not-in-bundle.test.ts +98 -0
- package/src/scenarios/v2-compensation-read-projection.test.ts +85 -0
- package/src/scenarios/v2-configurable-closed.test.ts +67 -0
- package/src/scenarios/v2-dual-stack-negotiation.test.ts +118 -0
- package/src/scenarios/v2-effect-identity-business-key.test.ts +132 -0
- package/src/scenarios/v2-effect-seam-manifest.test.ts +163 -0
- package/src/scenarios/v2-enum-growth-rule.test.ts +69 -0
- package/src/scenarios/v2-era-key.test.ts +86 -0
- package/src/scenarios/v2-error-registry.test.ts +89 -0
- package/src/scenarios/v2-event-type-closed.test.ts +97 -0
- package/src/scenarios/v2-fork-a-v1-run.test.ts +109 -0
- package/src/scenarios/v2-form-when-reuses-edge-conditions.test.ts +70 -0
- package/src/scenarios/v2-header-scheme.test.ts +67 -0
- package/src/scenarios/v2-id-grammar.test.ts +77 -0
- package/src/scenarios/v2-idempotency-key-grammar.test.ts +65 -0
- package/src/scenarios/v2-interrupt-token-scheme.test.ts +55 -0
- package/src/scenarios/v2-lane-issuer-advertised.test.ts +62 -0
- package/src/scenarios/v2-legacy-profiles-absent.test.ts +78 -0
- package/src/scenarios/v2-manifest-ceiling-refused.test.ts +130 -0
- package/src/scenarios/v2-manifest-hatch-carried.test.ts +120 -0
- package/src/scenarios/v2-min-client-version.test.ts +48 -0
- package/src/scenarios/v2-minimum-version-refused.test.ts +141 -0
- package/src/scenarios/v2-mrtr-rounds-ceiling.test.ts +95 -0
- package/src/scenarios/v2-negotiation-authenticated.test.ts +125 -0
- package/src/scenarios/v2-negotiation-decided-emitted.test.ts +149 -0
- package/src/scenarios/v2-no-transport-advertisement.test.ts +57 -0
- package/src/scenarios/v2-owner-subject-required.test.ts +72 -0
- package/src/scenarios/v2-pack-isolation.test.ts +147 -0
- package/src/scenarios/v2-payload-registry-closed.test.ts +110 -0
- package/src/scenarios/v2-peer-dependency-declared.test.ts +132 -0
- package/src/scenarios/v2-pinned-run-disposition.test.ts +124 -0
- package/src/scenarios/v2-poll-cursor-v2.test.ts +114 -0
- package/src/scenarios/v2-preferred-version-default.test.ts +83 -0
- package/src/scenarios/v2-profiles-derived-only.test.ts +70 -0
- package/src/scenarios/v2-provider-conflict.test.ts +115 -0
- package/src/scenarios/v2-refresh-sla.test.ts +78 -0
- package/src/scenarios/v2-relaxation-recorded.test.ts +134 -0
- package/src/scenarios/v2-revocation-honored.test.ts +66 -0
- package/src/scenarios/v2-subject-link-record.test.ts +102 -0
- package/src/scenarios/v2-unmapped-type-refused.test.ts +95 -0
- package/src/scenarios/v2-v1-events-translated.test.ts +105 -0
- package/src/scenarios/v2-v1-signed-webhook-accepted.test.ts +109 -0
- package/src/scenarios/v2-webhook-durable-delivery.test.ts +238 -0
- package/src/scenarios/v2-well-known-one-resource.test.ts +129 -0
- package/src/scenarios/vector-knn-roundtrip.test.ts +9 -7
- package/src/scenarios/verifier-gating.test.ts +8 -6
- package/src/scenarios/version-fold.test.ts +9 -8
- package/src/scenarios/version-negotiation.test.ts +12 -11
- package/src/scenarios/voice-bargein-no-partial-leak.test.ts +8 -6
- package/src/scenarios/voice-event-payloads-shape.test.ts +10 -11
- package/src/scenarios/voice-interim-not-durable.test.ts +7 -5
- package/src/scenarios/voice-streamref-tenant-bound.test.ts +5 -3
- package/src/scenarios/voice-synthesis-streaming.test.ts +11 -9
- package/src/scenarios/voice-transcription-streaming.test.ts +8 -6
- package/src/scenarios/voice-transcription-unadvertised.test.ts +5 -3
- package/src/scenarios/wasm-pack-abi-version-rejection.test.ts +3 -2
- package/src/scenarios/wasm-pack-invoke-completed.test.ts +3 -2
- package/src/scenarios/wasm-pack-invoke-suspended.test.ts +3 -2
- package/src/scenarios/wasm-pack-load.test.ts +4 -3
- package/src/scenarios/wasm-pack-memory-cap.test.ts +5 -4
- package/src/scenarios/wasm-pack-replay-determinism.test.ts +2 -1
- package/src/scenarios/webhook-negative.test.ts +11 -9
- package/src/scenarios/webhook-receiver-adversarial.test.ts +8 -7
- package/src/scenarios/webhook-sig-algorithm.test.ts +5 -3
- package/src/scenarios/webhook-signed-delivery.test.ts +16 -15
- package/src/scenarios/webhook-tenant-isolation.test.ts +16 -14
- package/src/scenarios/workflow-chain-deferred-parameters.test.ts +28 -30
- package/src/scenarios/workflow-chain-expansion.test.ts +21 -20
- package/src/scenarios/workflow-chain-host-expansion.test.ts +21 -20
- package/src/scenarios/workflow-chain-pack-manifest-validation.test.ts +14 -12
- package/src/scenarios/workflow-chain-pack-signature-verification.test.ts +5 -4
- package/src/scenarios/workflow-chain-unresolvable-typeid.test.ts +9 -8
- package/src/scenarios/workflow-primary-output-annotation.test.ts +7 -6
- package/src/scenarios/workflow-variable-format.test.ts +24 -24
- package/src/scenarios/workload-identity-behavior.test.ts +15 -13
- package/src/scenarios/workload-identity-chain-bounds.test.ts +18 -17
- package/src/scenarios/workspace-behavior.test.ts +19 -18
- package/src/scenarios/workspace-capability-shape.test.ts +3 -2
- package/src/scenarios/workspace-cross-tenant-isolation-blackbox.test.ts +6 -5
- package/src/scenarios/workspace-cross-tenant-isolation.test.ts +7 -6
- package/src/scenarios/x-openwop-form-pack-manifest.test.ts +8 -7
- package/src/setup.ts +44 -6
- package/vitest.config.ts +5 -1
- package/api/.redocly.lint-ignore.yaml +0 -22
- package/api/asyncapi.yaml +0 -834
- package/api/grpc/openwop.proto +0 -251
- package/api/openapi.yaml +0 -2693
- package/api/redocly.yaml +0 -23
- package/schemas/README.md +0 -144
- package/schemas/a2a-task-state.schema.json +0 -78
- package/schemas/a2ui-surface-delta-frame.schema.json +0 -48
- package/schemas/agent-deployment-transition.schema.json +0 -49
- package/schemas/agent-deployment.schema.json +0 -54
- package/schemas/agent-eval-suite.schema.json +0 -140
- package/schemas/agent-inventory-response.schema.json +0 -115
- package/schemas/agent-manifest.schema.json +0 -156
- package/schemas/agent-org-chart.schema.json +0 -82
- package/schemas/agent-ref.schema.json +0 -63
- package/schemas/agent-roster-entry.schema.json +0 -81
- package/schemas/agent-roster-response.schema.json +0 -21
- package/schemas/ai-envelope.schema.json +0 -134
- package/schemas/annotation-create.schema.json +0 -37
- package/schemas/annotation.schema.json +0 -56
- package/schemas/artifact-type-pack-manifest.schema.json +0 -244
- package/schemas/audit-verify-result.schema.json +0 -90
- package/schemas/budget-policy.schema.json +0 -18
- package/schemas/capabilities.schema.json +0 -4160
- package/schemas/certification-bundle-v2.schema.json +0 -118
- package/schemas/channel-presence-payload.schema.json +0 -41
- package/schemas/channel-written-payload.schema.json +0 -55
- package/schemas/chat-card-pack-manifest.schema.json +0 -253
- package/schemas/compact-tool-descriptor.schema.json +0 -51
- package/schemas/compensation-policy.schema.json +0 -64
- package/schemas/conformance-certification-bundle.schema.json +0 -86
- package/schemas/connection-pack-manifest.schema.json +0 -353
- package/schemas/conversation-event.schema.json +0 -168
- package/schemas/conversation-turn.schema.json +0 -117
- package/schemas/core-conformance-mock-agent-config.schema.json +0 -152
- package/schemas/credential-provenance.schema.json +0 -18
- package/schemas/credential-reference.schema.json +0 -21
- package/schemas/debug-bundle.schema.json +0 -196
- package/schemas/dispatch-config.schema.json +0 -112
- package/schemas/envelopes/clarification.request.schema.json +0 -52
- package/schemas/envelopes/error.schema.json +0 -30
- package/schemas/envelopes/media.audio.schema.json +0 -38
- package/schemas/envelopes/media.file.schema.json +0 -37
- package/schemas/envelopes/media.image.schema.json +0 -33
- package/schemas/envelopes/schema.request.schema.json +0 -26
- package/schemas/envelopes/schema.response.schema.json +0 -22
- package/schemas/envelopes/ui.a2ui-surface.schema.json +0 -154
- package/schemas/error-envelope.schema.json +0 -25
- package/schemas/eval-summary.schema.json +0 -92
- package/schemas/export-bundle.schema.json +0 -66
- package/schemas/form-content-pack-manifest.schema.json +0 -243
- package/schemas/frontend-plugin-manifest.schema.json +0 -109
- package/schemas/goal.schema.json +0 -104
- package/schemas/heartbeat-evaluated.schema.json +0 -14
- package/schemas/heartbeat-state-changed.schema.json +0 -14
- package/schemas/localized-content-language-settings.schema.json +0 -26
- package/schemas/localized-content-page-response.schema.json +0 -60
- package/schemas/localized-content-page.schema.json +0 -62
- package/schemas/localized-content-section.schema.json +0 -51
- package/schemas/memory-entry.schema.json +0 -36
- package/schemas/memory-list-options.schema.json +0 -37
- package/schemas/node-pack-manifest.schema.json +0 -654
- package/schemas/orchestrator-decision.schema.json +0 -90
- package/schemas/org-chart-responsibility-view.schema.json +0 -26
- package/schemas/pack-lockfile.schema.json +0 -108
- package/schemas/prompt-kind.schema.json +0 -8
- package/schemas/prompt-pack-manifest.schema.json +0 -117
- package/schemas/prompt-ref.schema.json +0 -40
- package/schemas/prompt-template.schema.json +0 -149
- package/schemas/proposal.schema.json +0 -84
- package/schemas/registry-version-manifest.schema.json +0 -208
- package/schemas/residency.schema.json +0 -16
- package/schemas/run-ancestry-response.schema.json +0 -54
- package/schemas/run-diff-response.schema.json +0 -64
- package/schemas/run-event-payloads.schema.json +0 -4452
- package/schemas/run-event.schema.json +0 -211
- package/schemas/run-options.schema.json +0 -80
- package/schemas/run-orchestrator-decided-event.schema.json +0 -20
- package/schemas/run-snapshot.schema.json +0 -148
- package/schemas/security-advisory.schema.json +0 -109
- package/schemas/self-hosted-runner-dispatch-frame.schema.json +0 -79
- package/schemas/self-hosted-runner-registration.schema.json +0 -53
- package/schemas/self-hosted-runner-result-frame.schema.json +0 -38
- package/schemas/subject.schema.json +0 -56
- package/schemas/suspend-request.schema.json +0 -207
- package/schemas/tool-descriptor.schema.json +0 -63
- package/schemas/trigger-event.schema.json +0 -222
- package/schemas/trigger-subscription-registration.schema.json +0 -67
- package/schemas/trigger-subscription.schema.json +0 -26
- package/schemas/ui-plugin-message.schema.json +0 -90
- package/schemas/workflow-chain-pack-manifest.schema.json +0 -615
- package/schemas/workflow-definition.schema.json +0 -850
- package/schemas/workload-identity.schema.json +0 -79
- package/schemas/workspace-file-create.schema.json +0 -20
- package/schemas/workspace-file.schema.json +0 -39
|
@@ -47,6 +47,7 @@ import Ajv2020 from 'ajv/dist/2020.js';
|
|
|
47
47
|
import addFormats from 'ajv-formats';
|
|
48
48
|
import type { ErrorObject } from 'ajv';
|
|
49
49
|
import { SCHEMAS_DIR } from '../lib/paths.js';
|
|
50
|
+
import { req } from '../lib/requirement-ids.js';
|
|
50
51
|
|
|
51
52
|
const SCHEMA_PATH = join(SCHEMAS_DIR, 'artifact-type-pack-manifest.schema.json');
|
|
52
53
|
|
|
@@ -87,7 +88,7 @@ describe('category: artifact-type-pack manifest validation', () => {
|
|
|
87
88
|
const ok = validate(validManifest());
|
|
88
89
|
expect(
|
|
89
90
|
ok,
|
|
90
|
-
`artifact-type-packs.md §"Manifest format": a well-formed kind:"artifact-type" manifest MUST validate. Errors: ${JSON.stringify(validate.errors)}
|
|
91
|
+
req('openwop.it.artifact-type-pack-manifest-validation.positive-a-valid-artifact-type-pack-manifest-validates-cleanly', 'artifact-type-packs.md', `artifact-type-packs.md §"Manifest format": a well-formed kind:"artifact-type" manifest MUST validate. Errors: ${JSON.stringify(validate.errors)}`),
|
|
91
92
|
).toBe(true);
|
|
92
93
|
});
|
|
93
94
|
|
|
@@ -96,45 +97,45 @@ describe('category: artifact-type-pack manifest validation', () => {
|
|
|
96
97
|
const errs = failsWith(manifest, 'additionalProperties');
|
|
97
98
|
expect(
|
|
98
99
|
errs.some((e) => (e.params as { additionalProperty?: string }).additionalProperty === 'nodes'),
|
|
99
|
-
'artifact-type-packs.md §"Pack kind": one kind per pack — a foreign `nodes[]` field MUST be rejected (additionalProperties:false)',
|
|
100
|
+
req('openwop.it.artifact-type-pack-manifest-validation.negative-a-manifest-mixing-artifacttypes-and-nodes-is-rejected-pack-kind-invalid', 'artifact-type-packs.md', 'artifact-type-packs.md §"Pack kind": one kind per pack — a foreign `nodes[]` field MUST be rejected (additionalProperties:false)'),
|
|
100
101
|
).toBe(true);
|
|
101
102
|
});
|
|
102
103
|
|
|
103
104
|
it('negative: an empty artifactTypes[] is rejected (a pack MUST declare ≥1 type)', () => {
|
|
104
105
|
const manifest = { ...validManifest(), artifactTypes: [] };
|
|
105
106
|
const errs = failsWith(manifest, 'minItems');
|
|
106
|
-
expect(errs.length, 'artifact-type-pack-manifest.schema.json: artifactTypes minItems:1').toBeGreaterThan(0);
|
|
107
|
+
expect(errs.length, req('openwop.it.artifact-type-pack-manifest-validation.negative-an-empty-artifacttypes-is-rejected-a-pack-must-declare-1-type', 'artifact-type-packs.md', 'artifact-type-pack-manifest.schema.json: artifactTypes minItems:1')).toBeGreaterThan(0);
|
|
107
108
|
});
|
|
108
109
|
|
|
109
110
|
it('negative: an artifactTypeId that is not reverse-DNS scoped is rejected', () => {
|
|
110
111
|
const manifest = validManifest();
|
|
111
112
|
manifest.artifactTypes[0]!.artifactTypeId = 'Vendor.Acme.Model'; // uppercase scope
|
|
112
113
|
const errs = failsWith(manifest, 'pattern');
|
|
113
|
-
expect(errs.length, 'artifact-type-packs.md: artifactTypeId MUST match the reverse-DNS pattern').toBeGreaterThan(0);
|
|
114
|
+
expect(errs.length, req('openwop.it.artifact-type-pack-manifest-validation.negative-an-artifacttypeid-that-is-not-reverse-dns-scoped-is-rejected', 'artifact-type-packs.md', 'artifact-type-packs.md: artifactTypeId MUST match the reverse-DNS pattern')).toBeGreaterThan(0);
|
|
114
115
|
});
|
|
115
116
|
|
|
116
117
|
it('negative: an unknown rendering.display value is rejected (closed RFC 0055 enum, card excluded)', () => {
|
|
117
118
|
const manifest = validManifest();
|
|
118
119
|
(manifest.artifactTypes[0]!.rendering as { display: string }).display = '3d-viewport';
|
|
119
120
|
const errs = failsWith(manifest, 'enum');
|
|
120
|
-
expect(errs.length, 'artifact-type-packs.md: rendering.display reuses the closed ai-envelope §"Rendering hints" enum').toBeGreaterThan(0);
|
|
121
|
+
expect(errs.length, req('openwop.it.artifact-type-pack-manifest-validation.negative-an-unknown-rendering-display-value-is-rejected-closed-rfc-0055-enum-car', 'RFC 0055', 'artifact-type-packs.md: rendering.display reuses the closed ai-envelope §"Rendering hints" enum')).toBeGreaterThan(0);
|
|
121
122
|
});
|
|
122
123
|
|
|
123
124
|
it('negative: a non-conforming exportFormats identifier is rejected (reserved-core + vendor.*/x- only)', () => {
|
|
124
125
|
const manifest = validManifest();
|
|
125
126
|
manifest.artifactTypes[0]!.exportFormats = ['PPTX']; // uppercase, unprefixed
|
|
126
127
|
const errs = failsWith(manifest, 'pattern');
|
|
127
|
-
expect(errs.length, 'artifact-type-packs.md: exportFormats identifiers are lowercase core ids OR vendor.*/x- extensions').toBeGreaterThan(0);
|
|
128
|
+
expect(errs.length, req('openwop.it.artifact-type-pack-manifest-validation.negative-a-non-conforming-exportformats-identifier-is-rejected-reserved-core-ven', 'artifact-type-packs.md', 'artifact-type-packs.md: exportFormats identifiers are lowercase core ids OR vendor.*/x- extensions')).toBeGreaterThan(0);
|
|
128
129
|
});
|
|
129
130
|
|
|
130
131
|
it('positive: the validation field accepts "open"/"closed" and rejects other values (RFC 0075)', () => {
|
|
131
132
|
for (const v of ['open', 'closed']) {
|
|
132
133
|
const m = validManifest();
|
|
133
134
|
(m.artifactTypes[0] as Record<string, unknown>).validation = v;
|
|
134
|
-
expect(validate(m), `artifact-type-packs.md §validation: "${v}" MUST validate (RFC 0075)`).toBe(true);
|
|
135
|
+
expect(validate(m), req('openwop.it.artifact-type-pack-manifest-validation.positive-the-validation-field-accepts-open-closed-and-rejects-other-values-rfc-0', 'RFC 0075', `artifact-type-packs.md §validation: "${v}" MUST validate (RFC 0075)`)).toBe(true);
|
|
135
136
|
}
|
|
136
137
|
const bad = validManifest();
|
|
137
138
|
(bad.artifactTypes[0] as Record<string, unknown>).validation = 'lenient';
|
|
138
|
-
expect(failsWith(bad, 'enum').length, 'validation MUST be open|closed').toBeGreaterThan(0);
|
|
139
|
+
expect(failsWith(bad, 'enum').length, req('openwop.it.artifact-type-pack-manifest-validation.positive-the-validation-field-accepts-open-closed-and-rejects-other-values-rfc-0', 'RFC 0075', 'validation MUST be open|closed')).toBeGreaterThan(0);
|
|
139
140
|
});
|
|
140
141
|
});
|
|
@@ -36,8 +36,8 @@ import { SCHEMAS_DIR, V1_DIR } from '../lib/paths.js';
|
|
|
36
36
|
import { driver } from '../lib/driver.js';
|
|
37
37
|
import { behaviorGatePresent } from '../lib/behavior-gate.js';
|
|
38
38
|
import { readArtifactTypesCap } from '../lib/artifactTypes.js';
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
import { req } from '../lib/requirement-ids.js';
|
|
40
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
41
41
|
const CAPS = join(SCHEMAS_DIR, 'capabilities.schema.json');
|
|
42
42
|
const EVENT_PAYLOADS = join(SCHEMAS_DIR, 'run-event-payloads.schema.json');
|
|
43
43
|
const readDoc = (name: string): string => (V1_DIR ? readFileSync(join(V1_DIR, name), 'utf8') : '');
|
|
@@ -59,14 +59,14 @@ describe('artifact-type-registration-source (RFC 0145, always-on)', () => {
|
|
|
59
59
|
const entry = perTypeEntry();
|
|
60
60
|
const props = entry.properties as Record<string, Record<string, unknown>>;
|
|
61
61
|
|
|
62
|
-
expect(props.registrationSource,
|
|
62
|
+
expect(props.registrationSource, req('openwop.it.artifact-type-registration-source.a1-the-per-type-entry-declares-registrationsource-as-an-optional-pack-host-enum', '§artifactTypes.types', 'facet is declared')).toBeDefined();
|
|
63
63
|
expect(
|
|
64
64
|
props.registrationSource.enum,
|
|
65
|
-
|
|
65
|
+
req('openwop.it.artifact-type-registration-source.a1-the-per-type-entry-declares-registrationsource-as-an-optional-pack-host-enum', '§artifactTypes.types', 'enum is exactly [pack, host]'),
|
|
66
66
|
).toEqual(['pack', 'host']);
|
|
67
67
|
expect(
|
|
68
68
|
(entry.required as string[] | undefined)?.includes('registrationSource') ?? false,
|
|
69
|
-
|
|
69
|
+
req('openwop.it.artifact-type-registration-source.a1-the-per-type-entry-declares-registrationsource-as-an-optional-pack-host-enum', '§artifactTypes.types', 'facet is OPTIONAL — absent ⇒ unspecified provenance, not a default'),
|
|
70
70
|
).toBe(false);
|
|
71
71
|
});
|
|
72
72
|
|
|
@@ -77,22 +77,22 @@ describe('artifact-type-registration-source (RFC 0145, always-on)', () => {
|
|
|
77
77
|
|
|
78
78
|
expect(
|
|
79
79
|
validate({ validated: true, registrationSource: 'host', schemaVersion: 1 }),
|
|
80
|
-
|
|
80
|
+
req('openwop.it.artifact-type-registration-source.a2-a-valid-provenance-validates-an-out-of-enum-value-does-not', '§artifactTypes.types', `"host" validates: ${JSON.stringify(validate.errors)}`),
|
|
81
81
|
).toBe(true);
|
|
82
82
|
expect(
|
|
83
83
|
validate({ validated: true, registrationSource: 'pack' }),
|
|
84
|
-
|
|
84
|
+
req('openwop.it.artifact-type-registration-source.a2-a-valid-provenance-validates-an-out-of-enum-value-does-not', '§artifactTypes.types', `"pack" validates: ${JSON.stringify(validate.errors)}`),
|
|
85
85
|
).toBe(true);
|
|
86
86
|
// Absent stays legal — requirement 2.
|
|
87
87
|
expect(
|
|
88
88
|
validate({ validated: true }),
|
|
89
|
-
|
|
89
|
+
req('openwop.it.artifact-type-registration-source.a2-a-valid-provenance-validates-an-out-of-enum-value-does-not', '§artifactTypes.types', `absent validates: ${JSON.stringify(validate.errors)}`),
|
|
90
90
|
).toBe(true);
|
|
91
91
|
// A third provenance is a wire error, NOT a hint to ignore. This is where the facet
|
|
92
92
|
// parts company with RFC 0136's `format`, and the reason is in the docblock.
|
|
93
93
|
expect(
|
|
94
94
|
validate({ validated: true, registrationSource: 'registry' }),
|
|
95
|
-
|
|
95
|
+
req('openwop.it.artifact-type-registration-source.a2-a-valid-provenance-validates-an-out-of-enum-value-does-not', '§artifactTypes.types', 'an undefined provenance is REJECTED'),
|
|
96
96
|
).toBe(false);
|
|
97
97
|
});
|
|
98
98
|
|
|
@@ -107,7 +107,7 @@ describe('artifact-type-registration-source (RFC 0145, always-on)', () => {
|
|
|
107
107
|
// advertise a provenance it could never emit.
|
|
108
108
|
expect(
|
|
109
109
|
entryProps.registrationSource.enum,
|
|
110
|
-
|
|
110
|
+
req('openwop.it.artifact-type-registration-source.a3-the-facet-mirrors-the-vocabulary-artifact-created-already-carries', 'RFC 0145 req 3', 'discovery enum matches artifact.created enum'),
|
|
111
111
|
).toEqual(eventProps.registrationSource.enum);
|
|
112
112
|
});
|
|
113
113
|
|
|
@@ -118,10 +118,10 @@ describe('artifact-type-registration-source (RFC 0145, always-on)', () => {
|
|
|
118
118
|
const facetList = readDoc(name).match(
|
|
119
119
|
/validated, validation, schemaVersion, store, render, export[^}]*}/,
|
|
120
120
|
);
|
|
121
|
-
expect(facetList,
|
|
121
|
+
expect(facetList, req('openwop.it.artifact-type-registration-source.a4-both-prose-sites-list-the-facet-so-schema-and-normative-surface-cannot-drift', `${name} §"Per-type facets"`, 'per-type facet list present')).not.toBeNull();
|
|
122
122
|
expect(
|
|
123
123
|
facetList?.[0].includes('registrationSource'),
|
|
124
|
-
|
|
124
|
+
req('openwop.it.artifact-type-registration-source.a4-both-prose-sites-list-the-facet-so-schema-and-normative-surface-cannot-drift', `${name} §"Per-type facets"`, 'facet list names registrationSource'),
|
|
125
125
|
).toBe(true);
|
|
126
126
|
}
|
|
127
127
|
});
|
|
@@ -130,11 +130,11 @@ describe('artifact-type-registration-source (RFC 0145, always-on)', () => {
|
|
|
130
130
|
const doc = readDoc('artifact-type-packs.md');
|
|
131
131
|
expect(
|
|
132
132
|
/Serving is a MUST for host-registered/.test(doc),
|
|
133
|
-
|
|
133
|
+
req('openwop.it.artifact-type-registration-source.a5-the-spec-states-the-must-should-asymmetry-the-facet-exists-to-disclose', '§Schema distribution', 'serving is a MUST for no-pack types'),
|
|
134
134
|
).toBe(true);
|
|
135
135
|
expect(
|
|
136
136
|
/serving stays a SHOULD for them/.test(doc),
|
|
137
|
-
|
|
137
|
+
req('openwop.it.artifact-type-registration-source.a5-the-spec-states-the-must-should-asymmetry-the-facet-exists-to-disclose', '§Schema distribution', 'serving stays a SHOULD for pack-backed types'),
|
|
138
138
|
).toBe(true);
|
|
139
139
|
});
|
|
140
140
|
});
|
|
@@ -179,7 +179,7 @@ describe('artifact-type-registration-source: the advert agrees with the event (R
|
|
|
179
179
|
const target = comparableType(cap);
|
|
180
180
|
// INAPPLICABLE, not gated. `registrationSource` is OPTIONAL (requirement 2) and strict mode
|
|
181
181
|
// must not coerce a host into advertising it — the same call RFC 0142 makes for `store`.
|
|
182
|
-
if (target === null) return;
|
|
182
|
+
if (target === null) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `target === null` returned early (INAPPLICABLE, not gated. `registrationSource` is OPTIONAL (requirement 2) and strict mode must not coerce a host into advertis…');
|
|
183
183
|
|
|
184
184
|
const started = await driver.post('/v1/host/sample/artifacttypes/runproduce', {
|
|
185
185
|
artifactTypeId: target.id,
|
|
@@ -189,10 +189,10 @@ describe('artifact-type-registration-source: the advert agrees with the event (R
|
|
|
189
189
|
// scenario that owns that enforcement. Gating again here would double-report one defect,
|
|
190
190
|
// and gating on the seam for a 0145 advert would coerce hosts into wiring 0142's host-sample
|
|
191
191
|
// surface in order to advertise a facet that has nothing to do with it.
|
|
192
|
-
if (started.status === 404 || started.status === 405) return; // seam absent — 0142 reports it
|
|
192
|
+
if (started.status === 404 || started.status === 405) return softSkip('blocked', 'precondition not met — `started.status === 404 || started.status === 405` returned early (seam absent — 0142 reports it) (seam, prior step, or fixture unavailable)'); // seam absent — 0142 reports it
|
|
193
193
|
expect(
|
|
194
194
|
started.status >= 200 && started.status < 300,
|
|
195
|
-
|
|
195
|
+
req('openwop.it.artifact-type-registration-source.the-emitted-registrationsource-equals-the-advertised-one-for-that-type', 'coverage.md §"Open seams"', 'runproduce starts a real run producing one artifact of the requested registered type'),
|
|
196
196
|
).toBe(true);
|
|
197
197
|
const runId = (started.json as Record<string, unknown> | undefined)?.['runId'];
|
|
198
198
|
if (!behaviorGatePresent(PROFILE, typeof runId === 'string' ? runId : null)) return;
|
|
@@ -200,18 +200,18 @@ describe('artifact-type-registration-source: the advert agrees with the event (R
|
|
|
200
200
|
const events = await driver.get(`/v1/runs/${runId}/events/poll?timeout=5`);
|
|
201
201
|
expect(
|
|
202
202
|
events.status,
|
|
203
|
-
|
|
203
|
+
req('openwop.it.artifact-type-registration-source.the-emitted-registrationsource-equals-the-advertised-one-for-that-type', 'run-events surface', 'the run event log is readable over the standard poll endpoint'),
|
|
204
204
|
).toBe(200);
|
|
205
205
|
const list = ((events.json as Record<string, unknown>)?.['events'] ?? []) as Array<Record<string, unknown>>;
|
|
206
206
|
const created = list.filter((e) => e['type'] === 'artifact.created');
|
|
207
207
|
// Emission itself is RFC 0142's MUST, reported by its own leg. Reaching here without an
|
|
208
208
|
// event means that leg is already red; don't restate its finding as a 0145 failure.
|
|
209
|
-
if (created.length === 0) return;
|
|
209
|
+
if (created.length === 0) return softSkip('blocked', 'precondition not met — `created.length === 0` returned early (Emission itself is RFC 0142\'s MUST, reported by its own leg. Reaching here without an event means that leg is already red; don\'t restate its finding as a 0…');
|
|
210
210
|
|
|
211
211
|
const payload = (created[0]?.['payload'] ?? created[0]?.['data'] ?? {}) as Record<string, unknown>;
|
|
212
212
|
expect(
|
|
213
213
|
payload['registrationSource'],
|
|
214
|
-
|
|
214
|
+
req('openwop.it.artifact-type-registration-source.the-emitted-registrationsource-equals-the-advertised-one-for-that-type',
|
|
215
215
|
'RFC 0145 requirement 3',
|
|
216
216
|
`the host advertises registrationSource: "${target.advertised}" for ${target.id}, so that is the value it MUST emit — an advert of one provenance against an event carrying another (or carrying none, which asserts UNSPECIFIED provenance and therefore disagrees) is a false advertisement, not a permitted divergence`,
|
|
217
217
|
),
|
|
@@ -43,31 +43,28 @@ import { driver } from '../lib/driver.js';
|
|
|
43
43
|
import { behaviorGate, behaviorGatePresent } from '../lib/behavior-gate.js';
|
|
44
44
|
import { readArtifactTypesCap } from '../lib/artifactTypes.js';
|
|
45
45
|
import { SCHEMAS_DIR, V1_DIR } from '../lib/paths.js';
|
|
46
|
+
import { req } from '../lib/requirement-ids.js';
|
|
47
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
46
48
|
|
|
47
49
|
const PROFILE = 'openwop-artifact-type-store';
|
|
48
50
|
|
|
49
|
-
/** Server-free assertion message helper — leg A must not touch `driver`, whose
|
|
50
|
-
* describe() loads env and would make a "server-free" leg fail on a missing
|
|
51
|
-
* OPENWOP_BASE_URL instead of on its assertion (a vacuous red). */
|
|
52
|
-
const why = (specRef: string, requirement: string): string => `${specRef} — ${requirement}`;
|
|
53
|
-
|
|
54
51
|
describe('artifact-type-store-emission: the payload fact is pinned always-on (RFC 0142 leg A)', () => {
|
|
55
52
|
it('artifactCreated REQUIRES artifactType — the fact the RFC 0138 replay correction rests on', () => {
|
|
56
53
|
const schema = JSON.parse(
|
|
57
54
|
readFileSync(join(SCHEMAS_DIR, 'run-event-payloads.schema.json'), 'utf8'),
|
|
58
55
|
) as { $defs?: Record<string, { properties?: Record<string, unknown>; required?: string[] }> };
|
|
59
56
|
const ac = schema.$defs?.['artifactCreated'];
|
|
60
|
-
expect(ac !== undefined, 'run-event-payloads.schema.json — $defs/artifactCreated exists').toBe(true);
|
|
57
|
+
expect(ac !== undefined, req('openwop.it.artifact-type-store-emission.artifactcreated-requires-artifacttype-the-fact-the-rfc-0138-replay-correction-re', 'RFC 0138', 'run-event-payloads.schema.json — $defs/artifactCreated exists')).toBe(true);
|
|
61
58
|
expect(
|
|
62
59
|
ac?.required?.includes('artifactType'),
|
|
63
|
-
|
|
60
|
+
req('openwop.it.artifact-type-store-emission.artifactcreated-requires-artifacttype-the-fact-the-rfc-0138-replay-correction-re',
|
|
64
61
|
'run-event-payloads.schema.json §artifactCreated',
|
|
65
62
|
'artifactType is REQUIRED on the artifact.created payload — artifactTypeId values ride in the fixed event log, which is why identifier migrations MUST NOT rewrite history (RFC 0141) and why this fact must be pinned by an always-on leg rather than a gated one (RFC 0138 G8)',
|
|
66
63
|
),
|
|
67
64
|
).toBe(true);
|
|
68
65
|
expect(
|
|
69
66
|
Object.keys(ac?.properties ?? {}).includes('registered'),
|
|
70
|
-
|
|
67
|
+
req('openwop.it.artifact-type-store-emission.artifactcreated-requires-artifacttype-the-fact-the-rfc-0138-replay-correction-re', 'run-event-payloads.schema.json §artifactCreated', 'the registered flag the store-tier validation promise is reported through is present'),
|
|
71
68
|
).toBe(true);
|
|
72
69
|
});
|
|
73
70
|
});
|
|
@@ -83,21 +80,21 @@ describe('artifact-type-store-emission: what `store: true` claims is stated norm
|
|
|
83
80
|
it.skipIf(V1_DIR === null)('the claim is quantified over artifacts of the type, not over the host\'s paths', () => {
|
|
84
81
|
expect(
|
|
85
82
|
/\*\*every\*\* path by which the host persists an artifact carrying that registered `artifactTypeId` MUST emit `artifact\.created`/.test(doc),
|
|
86
|
-
|
|
83
|
+
req('openwop.it.artifact-type-store-emission.the-claim-is-quantified-over-artifacts-of-the-type-not-over-the-host-s-paths',
|
|
87
84
|
'artifact-type-packs.md §"Sub-flags"',
|
|
88
85
|
'EVERY production path emits, not at least one — the permissive reading lets a host wire the leg-B seam through its single emitting path and pass while most of its production stays silent',
|
|
89
86
|
),
|
|
90
87
|
).toBe(true);
|
|
91
88
|
expect(
|
|
92
89
|
/MUST NOT advertise `store: true` for that type/.test(doc),
|
|
93
|
-
|
|
90
|
+
req('openwop.it.artifact-type-store-emission.the-claim-is-quantified-over-artifacts-of-the-type-not-over-the-host-s-paths', 'artifact-type-packs.md §"Sub-flags"', 'a host with a silent persistence path for the type is forbidden from advertising it, rather than merely discouraged'),
|
|
94
91
|
).toBe(true);
|
|
95
92
|
});
|
|
96
93
|
|
|
97
94
|
it.skipIf(V1_DIR === null)('the obligation is scoped to REGISTERED types, so the unregistered tier does not falsify an advert', () => {
|
|
98
95
|
expect(
|
|
99
96
|
/a path that persists only unregistered artifacts[^.]*is outside this facet and does not falsify the advert/.test(doc),
|
|
100
|
-
|
|
97
|
+
req('openwop.it.artifact-type-store-emission.the-obligation-is-scoped-to-registered-types-so-the-unregistered-tier-does-not-f',
|
|
101
98
|
'artifact-type-packs.md §"Sub-flags"',
|
|
102
99
|
'the narrowing is normative, not a courtesy — without it a host holds back an honest advert on account of a path the facet never bound',
|
|
103
100
|
),
|
|
@@ -107,7 +104,7 @@ describe('artifact-type-store-emission: what `store: true` claims is stated norm
|
|
|
107
104
|
it.skipIf(V1_DIR === null)('per-type is named as the instrument, including the case it cannot rescue', () => {
|
|
108
105
|
expect(
|
|
109
106
|
/cannot be advertised `store: true` at all until one of those two facts changes/.test(doc),
|
|
110
|
-
|
|
107
|
+
req('openwop.it.artifact-type-store-emission.per-type-is-named-as-the-instrument-including-the-case-it-cannot-rescue',
|
|
111
108
|
'artifact-type-packs.md §"Sub-flags"',
|
|
112
109
|
'a single type produced through both an emitting and a non-emitting path is not advertisable — per-type resolves a heterogeneous fleet, not a heterogeneous type',
|
|
113
110
|
),
|
|
@@ -144,7 +141,7 @@ describe('artifact-type-store-emission: a store:true host MUST emit, witnessed f
|
|
|
144
141
|
const cap = await readArtifactTypesCap();
|
|
145
142
|
// `store` is OPTIONAL. A host that does not advertise it is INAPPLICABLE —
|
|
146
143
|
// not gated: strict mode must not coerce hosts into an advertisement.
|
|
147
|
-
if (!storeAdvertised(cap)) return; // scenario inapplicable
|
|
144
|
+
if (!storeAdvertised(cap)) return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!storeAdvertised(cap)` returned early (scenario inapplicable)'); // scenario inapplicable
|
|
148
145
|
|
|
149
146
|
const requested = storeTypeId(cap) ?? 'vendor.conformance.note';
|
|
150
147
|
const started = await driver.post('/v1/host/sample/artifacttypes/runproduce', {
|
|
@@ -155,7 +152,7 @@ describe('artifact-type-store-emission: a store:true host MUST emit, witnessed f
|
|
|
155
152
|
|
|
156
153
|
expect(
|
|
157
154
|
started.status >= 200 && started.status < 300,
|
|
158
|
-
|
|
155
|
+
req('openwop.it.artifact-type-store-emission.artifact-created-appears-in-the-event-log-with-the-bound-artifacttype-and-regist', 'coverage.md §"Open seams"', 'runproduce starts a real run producing one artifact of the requested registered type'),
|
|
159
156
|
).toBe(true);
|
|
160
157
|
const runId = (started.json as Record<string, unknown> | undefined)?.['runId'];
|
|
161
158
|
if (!behaviorGatePresent(PROFILE, typeof runId === 'string' ? runId : null)) return;
|
|
@@ -163,14 +160,14 @@ describe('artifact-type-store-emission: a store:true host MUST emit, witnessed f
|
|
|
163
160
|
const events = await driver.get(`/v1/runs/${runId}/events/poll?timeout=5`);
|
|
164
161
|
expect(
|
|
165
162
|
events.status,
|
|
166
|
-
|
|
163
|
+
req('openwop.it.artifact-type-store-emission.artifact-created-appears-in-the-event-log-with-the-bound-artifacttype-and-regist', 'run-events surface', 'the run event log is readable over the standard poll endpoint — the same wire any consumer uses'),
|
|
167
164
|
).toBe(200);
|
|
168
165
|
const list = ((events.json as Record<string, unknown>)?.['events'] ?? []) as Array<Record<string, unknown>>;
|
|
169
166
|
const created = list.filter((e) => e['type'] === 'artifact.created');
|
|
170
167
|
|
|
171
168
|
expect(
|
|
172
169
|
created.length > 0,
|
|
173
|
-
|
|
170
|
+
req('openwop.it.artifact-type-store-emission.artifact-created-appears-in-the-event-log-with-the-bound-artifacttype-and-regist',
|
|
174
171
|
'artifact-type-packs.md §"Host capability", store row',
|
|
175
172
|
'a host advertising store:true MUST emit artifact.created — persistence without emission is the exact posture the advertisement forbids',
|
|
176
173
|
),
|
|
@@ -179,14 +176,14 @@ describe('artifact-type-store-emission: a store:true host MUST emit, witnessed f
|
|
|
179
176
|
const payload = (created[0]?.['payload'] ?? created[0]?.['data'] ?? {}) as Record<string, unknown>;
|
|
180
177
|
expect(
|
|
181
178
|
payload['artifactType'],
|
|
182
|
-
|
|
179
|
+
req('openwop.it.artifact-type-store-emission.artifact-created-appears-in-the-event-log-with-the-bound-artifacttype-and-regist',
|
|
183
180
|
'run-event-payloads.schema.json §artifactCreated',
|
|
184
181
|
'the emitted artifactType is the bound id — an event present but carrying the wrong type would let a mis-wired emitter pass a presence-only check',
|
|
185
182
|
),
|
|
186
183
|
).toBe(requested);
|
|
187
184
|
expect(
|
|
188
185
|
payload['registered'],
|
|
189
|
-
|
|
186
|
+
req('openwop.it.artifact-type-store-emission.artifact-created-appears-in-the-event-log-with-the-bound-artifacttype-and-regist',
|
|
190
187
|
'artifact-type-packs.md §"Binding the existing artifact surfaces"',
|
|
191
188
|
'a store-tier host validates before emitting and reports registered:true for a registered type',
|
|
192
189
|
),
|
|
@@ -25,7 +25,6 @@
|
|
|
25
25
|
|
|
26
26
|
import { describe, it, expect } from 'vitest';
|
|
27
27
|
import { softSkip } from '../lib/soft-skip.js';
|
|
28
|
-
import { driver } from '../lib/driver.js';
|
|
29
28
|
import { behaviorGate, behaviorGatePresent } from '../lib/behavior-gate.js';
|
|
30
29
|
|
|
31
30
|
const PROFILE = 'openwop-artifact-type-packs';
|
|
@@ -36,6 +35,7 @@ import {
|
|
|
36
35
|
produceArtifact,
|
|
37
36
|
sampleArtifactTypePack,
|
|
38
37
|
} from '../lib/artifactTypes.js';
|
|
38
|
+
import { req } from '../lib/requirement-ids.js';
|
|
39
39
|
|
|
40
40
|
describe('artifact-type-store-without-render: store-only hosts must not fail the run (RFC 0071)', () => {
|
|
41
41
|
it('a stored-but-unrendered artifact completes the run', async () => {
|
|
@@ -54,15 +54,15 @@ describe('artifact-type-store-without-render: store-only hosts must not fail the
|
|
|
54
54
|
|
|
55
55
|
expect(
|
|
56
56
|
produced.json['stored'],
|
|
57
|
-
|
|
57
|
+
req('openwop.it.artifact-type-store-without-render.a-stored-but-unrendered-artifact-completes-the-run', 'artifact-type-packs.md §host.artifactTypes', 'a host advertising store:true MUST persist the artifact'),
|
|
58
58
|
).toBe(true);
|
|
59
59
|
expect(
|
|
60
60
|
produced.json['rendered'],
|
|
61
|
-
|
|
61
|
+
req('openwop.it.artifact-type-store-without-render.a-stored-but-unrendered-artifact-completes-the-run', 'artifact-type-packs.md §host.artifactTypes', 'render:false host MUST NOT render'),
|
|
62
62
|
).toBe(false);
|
|
63
63
|
expect(
|
|
64
64
|
produced.json['runStatus'],
|
|
65
|
-
|
|
65
|
+
req('openwop.it.artifact-type-store-without-render.a-stored-but-unrendered-artifact-completes-the-run', 'artifact-type-packs.md §host.artifactTypes', 'a host MUST NOT fail the run solely because it lacks a renderer for a stored artifact type'),
|
|
66
66
|
).toBe('completed');
|
|
67
67
|
});
|
|
68
68
|
});
|
|
@@ -19,6 +19,8 @@ import { describe, it, expect } from 'vitest';
|
|
|
19
19
|
import { driver } from '../lib/driver.js';
|
|
20
20
|
import { behaviorGate } from '../lib/behavior-gate.js';
|
|
21
21
|
import { capabilityFamily } from '../lib/discovery-capabilities.js';
|
|
22
|
+
import { req } from '../lib/requirement-ids.js';
|
|
23
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
22
24
|
|
|
23
25
|
interface AuditIntegrityCaps {
|
|
24
26
|
hashChain?: boolean;
|
|
@@ -50,11 +52,11 @@ describe('audit-log-integrity: profile shape', () => {
|
|
|
50
52
|
capabilityFamily<AuthCaps>(disco.json, 'auth')
|
|
51
53
|
?.auditLogIntegrity ?? {};
|
|
52
54
|
|
|
53
|
-
expect(integrity.hashChain,
|
|
55
|
+
expect(integrity.hashChain, req('openwop.it.audit-log-integrity.host-that-claims-the-profile-advertises-required-capability-fields',
|
|
54
56
|
'auth-profiles.md §"Audit-log integrity"',
|
|
55
57
|
"openwop-audit-log-integrity profile MUST advertise auditLogIntegrity.hashChain: true",
|
|
56
58
|
)).toBe(true);
|
|
57
|
-
expect(integrity.checkpointSignatureAlgorithm,
|
|
59
|
+
expect(integrity.checkpointSignatureAlgorithm, req('openwop.it.audit-log-integrity.host-that-claims-the-profile-advertises-required-capability-fields',
|
|
58
60
|
'auth-profiles.md §"Audit-log integrity" §"Key management"',
|
|
59
61
|
'checkpointSignatureAlgorithm MUST be present (canonical: ed25519)',
|
|
60
62
|
)).toBeDefined();
|
|
@@ -72,11 +74,11 @@ describe('audit-log-integrity: verify endpoint returns chainValid', () => {
|
|
|
72
74
|
if (verify.status === 404) {
|
|
73
75
|
// Host claims the profile but doesn't expose the endpoint — that's
|
|
74
76
|
// a profile-claim violation. Fail explicitly.
|
|
75
|
-
expect(verify.status,
|
|
77
|
+
expect(verify.status, req('openwop.it.audit-log-integrity.get-v1-audit-verify-on-a-recent-range-reports-chainvalid-true',
|
|
76
78
|
'auth-profiles.md §"Audit-log integrity" §"Verification endpoint"',
|
|
77
79
|
'claiming openwop-audit-log-integrity profile REQUIRES exposing GET /v1/audit/verify',
|
|
78
80
|
)).not.toBe(404);
|
|
79
|
-
return;
|
|
81
|
+
return softSkip('blocked', 'precondition not met — `verify.status === 404` returned early (seam, prior step, or fixture unavailable)');
|
|
80
82
|
}
|
|
81
83
|
expect(verify.status).toBe(200);
|
|
82
84
|
|
|
@@ -88,7 +90,7 @@ describe('audit-log-integrity: verify endpoint returns chainValid', () => {
|
|
|
88
90
|
anomalies?: unknown[];
|
|
89
91
|
};
|
|
90
92
|
|
|
91
|
-
expect(body.chainValid,
|
|
93
|
+
expect(body.chainValid, req('openwop.it.audit-log-integrity.get-v1-audit-verify-on-a-recent-range-reports-chainvalid-true',
|
|
92
94
|
'auth-profiles.md §"Audit-log integrity"',
|
|
93
95
|
'unmodified audit range MUST report chainValid: true',
|
|
94
96
|
)).toBe(true);
|
|
@@ -97,7 +99,7 @@ describe('audit-log-integrity: verify endpoint returns chainValid', () => {
|
|
|
97
99
|
|
|
98
100
|
if (Array.isArray(body.checkpoints) && body.checkpoints.length > 0) {
|
|
99
101
|
const cp = body.checkpoints[0];
|
|
100
|
-
expect(typeof cp.signature, 'checkpoint signature MUST be a non-empty string').toBe('string');
|
|
102
|
+
expect(typeof cp.signature, req('openwop.it.audit-log-integrity.get-v1-audit-verify-on-a-recent-range-reports-chainvalid-true', 'auth-profiles.md §"Audit-log integrity"', 'checkpoint signature MUST be a non-empty string')).toBe('string');
|
|
101
103
|
expect((cp.signature ?? '').length).toBeGreaterThan(0);
|
|
102
104
|
}
|
|
103
105
|
});
|
|
@@ -29,6 +29,8 @@ import { driver } from '../lib/driver.js';
|
|
|
29
29
|
import { behaviorGate } from '../lib/behavior-gate.js';
|
|
30
30
|
import { isFixtureAdvertised } from '../lib/fixtures.js';
|
|
31
31
|
import { capabilityFamily } from '../lib/discovery-capabilities.js';
|
|
32
|
+
import { req } from '../lib/requirement-ids.js';
|
|
33
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
32
34
|
|
|
33
35
|
interface RotationCaps {
|
|
34
36
|
supported?: boolean;
|
|
@@ -65,12 +67,12 @@ describe('auth-api-key-rotation: capability shape', () => {
|
|
|
65
67
|
return;
|
|
66
68
|
}
|
|
67
69
|
|
|
68
|
-
expect(auth?.profiles?.includes(PROFILE),
|
|
70
|
+
expect(auth?.profiles?.includes(PROFILE), req('openwop.it.auth-api-key-rotation.host-claiming-rotation-profile-advertises-required-fields',
|
|
69
71
|
'auth-profiles.md §`openwop-auth-api-key-rotation`',
|
|
70
72
|
'capabilities.auth.profiles MUST include openwop-auth-api-key-rotation when the profile is claimed',
|
|
71
73
|
)).toBe(true);
|
|
72
74
|
|
|
73
|
-
expect(auth?.rotation?.supported,
|
|
75
|
+
expect(auth?.rotation?.supported, req('openwop.it.auth-api-key-rotation.host-claiming-rotation-profile-advertises-required-fields',
|
|
74
76
|
'auth-profiles.md §`openwop-auth-api-key-rotation`',
|
|
75
77
|
'capabilities.auth.rotation.supported MUST be true when the profile is claimed',
|
|
76
78
|
)).toBe(true);
|
|
@@ -79,7 +81,7 @@ describe('auth-api-key-rotation: capability shape', () => {
|
|
|
79
81
|
expect(
|
|
80
82
|
Number.isInteger(auth.rotation.minGraceSeconds) &&
|
|
81
83
|
auth.rotation.minGraceSeconds >= 0,
|
|
82
|
-
|
|
84
|
+
req('openwop.it.auth-api-key-rotation.host-claiming-rotation-profile-advertises-required-fields',
|
|
83
85
|
'capabilities.schema.json auth.rotation.minGraceSeconds',
|
|
84
86
|
'minGraceSeconds MUST be a non-negative integer when advertised',
|
|
85
87
|
),
|
|
@@ -109,7 +111,7 @@ describe('auth-api-key-rotation: two-key overlap', () => {
|
|
|
109
111
|
console.warn(
|
|
110
112
|
'[auth-api-key-rotation] OPENWOP_TEST_SECONDARY_API_KEY not supplied; skipping two-key overlap assertion',
|
|
111
113
|
);
|
|
112
|
-
return;
|
|
114
|
+
return softSkip('blocked', 'precondition not met — `!secondaryKey` returned early ([auth-api-key-rotation] OPENWOP_TEST_SECONDARY_API_KEY not supplied; skipping two-key overlap assertion) (seam, prior step, or fixture unavailable)');
|
|
113
115
|
}
|
|
114
116
|
|
|
115
117
|
if (!isFixtureAdvertised(FIXTURE)) {
|
|
@@ -117,12 +119,12 @@ describe('auth-api-key-rotation: two-key overlap', () => {
|
|
|
117
119
|
console.warn(
|
|
118
120
|
`[auth-api-key-rotation] ${FIXTURE} not advertised; skipping overlap assertion`,
|
|
119
121
|
);
|
|
120
|
-
return;
|
|
122
|
+
return softSkip('inapplicable', 'capability or profile not advertised by this host — gate `!isFixtureAdvertised(FIXTURE)` returned early ([auth-api-key-rotation] … not advertised; skipping overlap assertion)');
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
// Primary key — uses driver's default Authorization header (env-loaded).
|
|
124
126
|
const primary = await driver.post('/v1/runs', { workflowId: FIXTURE });
|
|
125
|
-
expect(primary.status,
|
|
127
|
+
expect(primary.status, req('openwop.it.auth-api-key-rotation.primary-secondary-keys-both-authenticate-the-same-operation',
|
|
126
128
|
'auth-profiles.md §`openwop-auth-api-key-rotation`',
|
|
127
129
|
'primary key MUST authenticate POST /v1/runs during rotation grace',
|
|
128
130
|
)).toBe(201);
|
|
@@ -137,7 +139,7 @@ describe('auth-api-key-rotation: two-key overlap', () => {
|
|
|
137
139
|
headers: { Authorization: `Bearer ${secondaryKey}` },
|
|
138
140
|
},
|
|
139
141
|
);
|
|
140
|
-
expect(secondary.status,
|
|
142
|
+
expect(secondary.status, req('openwop.it.auth-api-key-rotation.primary-secondary-keys-both-authenticate-the-same-operation',
|
|
141
143
|
'auth-profiles.md §`openwop-auth-api-key-rotation`',
|
|
142
144
|
'secondary key MUST authenticate POST /v1/runs during rotation grace',
|
|
143
145
|
)).toBe(201);
|
|
@@ -167,7 +169,7 @@ describe('auth-api-key-rotation: canary redaction', () => {
|
|
|
167
169
|
},
|
|
168
170
|
);
|
|
169
171
|
|
|
170
|
-
expect(res.status,
|
|
172
|
+
expect(res.status, req('openwop.it.auth-api-key-rotation.invalid-bearer-returns-401-without-echoing-the-canary-credential',
|
|
171
173
|
'auth.md §3',
|
|
172
174
|
'invalid bearer MUST return 401, not 200 or 403',
|
|
173
175
|
)).toBe(401);
|
|
@@ -175,7 +177,7 @@ describe('auth-api-key-rotation: canary redaction', () => {
|
|
|
175
177
|
// The response body MUST NOT echo the canary in any field. We
|
|
176
178
|
// check the serialized JSON to catch echoes even in nested fields.
|
|
177
179
|
const serialized = JSON.stringify(res.json ?? {});
|
|
178
|
-
expect(serialized.includes(CANARY),
|
|
180
|
+
expect(serialized.includes(CANARY), req('openwop.it.auth-api-key-rotation.invalid-bearer-returns-401-without-echoing-the-canary-credential',
|
|
179
181
|
'auth.md §"No credential echo" + threat-model-auth-profiles.md A1',
|
|
180
182
|
'rotation-profile hosts MUST NOT echo the rejected credential in error responses',
|
|
181
183
|
)).toBe(false);
|