All notable changes to the QWED Protocol will be documented in this file.
- ADR-001..005 — verification ontology — formally define the object of verification, the verification context document, the truth-vs-admission separation, the formalization boundary, and the root of trust.
- Verification Context v1.0 spec freeze — the 4-layer JSON document contract (interpretation / proof / evidence / decision) with canonical RFC 8785 JSON encoding, UTF-16 key ordering, fail-closed schema validation, and content-bound
proof_ref.
VerificationContextmodel + JSON schema —VerificationContext,VerificationContextDocument,Verdict,Admission, and nestedInterpretation/Proof/Evidence/Decisiontypes with fail-closed validation.- Public proof_ref generation / resolution —
compute_document_proof_ref()andresolve_document_proof_ref()exposed as public API; references are content-bound SHA-256 hashes over the canonical document.
verification_context_from_diagnostic_result()— convertsDiagnosticResult→ VC document; VERIFIED without attestation demotes to UNVERIFIABLE (fail-closed, consistent with the core contract).to_verification_context()on all 13 verifiers — complete engine coverage: Math, Logic, Symbolic, SQL, Code, Schema, Fact, Image, Graph, Reasoning, Stats, Consensus, and SecureCodeExecutor.
- SDK / API / CLI exposure — Verification Context surfaced across the API routes, CLI, and SDK.
- Docker action VC outputs — the containerized GitHub Action emits
verdict,admission,proof_ref, andverification_contextoutputs. - Metadata & README alignment — repository metadata aligned with the v7.0 architecture.
- SDK re-exports — all Verification Context v1.0 types re-exported from
qwed_sdk.
Semver: minor release — additive public API (VC model, mappings, resolver, routes, outputs). No breaking wire changes.
SchemaVerifier.verify()andverify_ucp_transaction()now returnDiagnosticResult(status /agent_message/developer_fields/proof_ref) instead of ad-hoc dicts.proof_refis computed deterministically from a canonicaljson.dumpsof the schema + instance evidence on VERIFIED results; unsupported values and cyclic structures fail closed toBLOCKED(schema_verifier.validation_error).- Recursive schema meta-validation — malformed keyword shapes (non-dict properties, invalid required entries, invalid numeric constraints, non-finite/NaN/±∞ bounds, negative size constraints) return
BLOCKED(schema_verifier.parse_error) instead of being silently treated as empty. - UCP type safety — string/None amount fields and non-dict transactions are handled deterministically instead of raising
TypeError/AttributeError. - UCP verdict fields are complete on every path —
verify_ucp_transaction()always producestransaction_type,currency, andschema_verifier.ucp_*constraint ids indeveloper_fieldsfor both valid and violated verdicts (BLOCKED base results pass through unchanged). - Money arithmetic uses
Decimal, not float tolerance — computed-total and tax checks quantize operands to the currency precision and compare exactly, removing 0.01-tolerance rounding noise so boundary transactions deterministically pass/fail. taxis selected by key presence, not truthiness — a declaredtax: 0is used instead of silently falling back totax_amount.- Non-finite floats (
NaN,±inf) and hostile__repr__set members fail closed — evidence serialization raisesValueErrorinto the existingBLOCKEDpath instead of emitting non-JSON tokens or leakingRuntimeError. agent_messagesanitized — no rule IDs, issue types, or schema internals leak into agent-facing output.- Removed orphan
math_verifierdelegation — the lazySymbolicVerifierinstantiation (never called) is gone; computed-field checks use inline exact Decimal comparison. - Hot path cost of the migration reduced (~20% fewer instructions) — proof evidence is traversed once instead of twice (cycles and unsupported types are detected by the canonical encoder itself), the canonical JSON encoder is reused across calls, and schema meta-validation dispatches on the keywords a schema declares instead of probing the full keyword vocabulary.
proof_refvalues are unchanged. - Oversized integer bounds no longer crash —
minimum/maximum/exclusiveMinimum/exclusiveMaximum/multipleOfvalues beyond float range (e.g.10**1000) are finite by construction and no longer raiseOverflowErrorout ofverify().
CodeVerifier.verify_code(),verify_python_deep(), andverify_batch()now returnDiagnosticResult(status /agent_message/developer_fields/proof_ref) instead of ad-hoc dicts.VERIFIEDis now emitted for unsafe code — asVERIFIED-as-unsafe. A proven-unsafe snippet isVERIFIEDwithdeveloper_fields.is_valid = false, a boundproof_ref, and a non-nullcritical_count; it is never emittedBLOCKED. This isVERIFIEDas a truth guarantee (the code was checked), not an admission guarantee.AdmissionDecisionis a separate decision, exposed at the trust boundary —POST /verify/codeand batchCODEitems attachadmission(ADMIT/BLOCKED) and treatis_validas the safety gate, so authority-only consumers readingstatus == "VERIFIED"cannot admit unsafe code.BLOCKEDis reserved for cases where verification itself failed — empty code, non-stringlanguage, internal/execution errors, and (deep) language normalization failures. Blocked results carry noproof_ref, so they cannot be mistaken for a verdict.SecureCodeExecutor.execute()no longer executes code wholesale on the verifier verdict — the executor applies an unconditional OWASP LLM06 dangerous-pattern gate (os.,sys.,subprocess,__import__,eval,exec,compile,open(,file(,input(,raw_input(,socket,urllib,requests,http) and blocks execution withCONSTRAINT_DANGEROUS_PATTERN. The scan is AST-aware: it matches actual executable operations (imports, attribute access, calls), so dangerous keywords that appear only in comments, docstrings, or string literals (e.g. a URL in a docstring) do not cause false denials. The advisory-only fallback is retained only when verification itself fails closed.verify_batch()returns per-itemverdicts+ asummaryand an overallis_valid—safe/unsafe/blockedcounts andtotal_critical;is_validistrueonly when all snippets are safe, and the batch is otherwise non-admissible.ConsensusVerifierandStatsVerifiercode-stages adapt — expected-status flags were updated to requireis_verifiedanddeveloper_fields.is_valid is True, andstats_verifier._validate_securityfails closed on any non-trueis_valid, so consensus results can no longer admit unsafe code.
Breaking wire change:
POST /verify/codenow returns HTTP 200 withstatus = "VERIFIED"for proven-unsafe code (previouslystatus = "BLOCKED"). Admission is driven by the newadmissionfield anddeveloper_fields.is_valid. Consumers that branched onstatus == "BLOCKED"orstatus == "VERIFIED"for safety gating must switch to theadmission/is_validfields;status == "VERIFIED"alone must never be treated as "safe to execute".
StatsVerifier.verify_stats()now returnsDiagnosticResult(status /agent_message/developer_fields/proof_ref) instead of an ad-hoc dict.- Execution success is never
VERIFIED(computation ≠ verification). A run that executes cleanly in the Docker sandbox and returns an observed statistic isUNVERIFIABLE(stats_verifier.claim_not_verified) — the engine has no deterministic claim-proof, so it cannot attest the original natural-language claim.VERIFIED+proof_refis reserved for a deterministic claim evaluation tracked in #298; it is never emitted from execution success alone. BLOCKEDis reserved for failure states — translation/validation failure (stats_verifier.validation_error), execution failure (stats_verifier.execution_failure), and secure Docker sandbox unavailable (stats_verifier.runtime_unavailable). Blocked results carry noproof_ref.- Execution evidence is preserved, not lost. On
UNVERIFIABLEthe observed result, generated code, columns, a deterministic dataset fingerprint (dataset_sha256), sandbox type, timing, and security checks are retained indeveloper_fieldsfor audit/review. agent_messageis sanitized — no raw subprocess output, sandbox identifiers, or error strings leak into the agent-facing layer.- API boundary is now a thin pass-through —
POST /verify/statsforwards the engine'sDiagnosticResultthroughenforce_trust_decision()unchanged instead of re-deriving status from dict fields. - Logging is fail-closed and claim-aware — the verification log records
is_verifiedfrom the authoritative proof bit AND the claim-validity signal (dr.is_authoritative and developer_fields.is_valid is True). A non-authoritative result (BLOCKED / UNVERIFIABLE,proof_ref = None) can never be persisted as verified, even if the mutabledeveloper_fields.is_validmetadata isTrue. compute_statistics()andget_sandbox_info()are deliberately unchanged — they are utilities (safe direct computation / sandbox introspection), not claim-verification boundaries, so they stay on their existing dict return.- Deferred architecture is tracked, not silently dropped — deterministic statistical claim evaluation (#298) and deterministic DataFrame schema validation (#299) do not exist in the codebase and were not invented here; both are filed as dedicated issues rather than being fabricated to force a
VERIFIED. FactVerifier/ImageVerifierbatch verification now returnsDiagnosticResult—BatchFactVerifier.verify_batch()andImageVerifier.verify_batch()return a singleDiagnosticResultwith per-claim verdicts indeveloper_fields.resultsand asummary. The batch is authoritative (VERIFIED+proof_ref) only when every claim is deterministically verified; any refuted/blocked claim fails the whole batch closed (fact_verifier.batch_blocked/image_verifier.batch_blocked), and an empty batch isBLOCKED(*.empty_batch). The batchproof_refbinds full claim digests and the shared input (image digest for image batches, context digest for fact batches), never truncated display text. Aggregation is shared viadiagnostics.aggregate_batch_diagnostic()so the fail-closed logic cannot drift between engines. This closes the last two public engine entry points still returning ad-hoc dicts under META #216.- Stats
observed_resultis JSON-safe — a non-serializable sandbox result (e.g. a DataFrame) is coerced before enteringdeveloper_fields, so a legitimateUNVERIFIABLEverdict can no longer be silently downgraded toBLOCKEDwhen the trust gate snapshots developer fields.
Breaking wire change:
POST /verify/statsnow returns the unifiedDiagnosticResultschema (status/agent_message/developer_fields/proof_ref) instead of the legacy{"status": "SUCCESS" | "ERROR" | "BLOCKED", "result": ..., "code": ...}shape. Successful execution now reportsstatus = "UNVERIFIABLE"with the observed value indeveloper_fields.observed_result— execution success alone is never presented as a proven claim.
qwed(PyPI):6.0.0->7.0.0qwed_sdk(Python):6.0.0->7.0.0@qwed-ai/sdk(NPM):6.0.0->7.0.0qwed(crates.io/Rust):6.0.0->7.0.0- API version marker:
6.0.0->7.0.0 - Kubernetes deployment image: stays pinned to the published
6.0.0here; bumped to7.0.0only after the release publishes the image (avoidsImagePullBackOff) - Deployment docs version references updated
#294feat(core): migrate SchemaVerifier to DiagnosticResult (#255)#295fix(sql): migrate SQLVerifier to DiagnosticResult (#253)#296feat(core): migrate CodeVerifier and SecureCodeExecutor to DiagnosticResult (#254)#297feat(stats): migrate StatsVerifier.verify_stats to DiagnosticResult (#256)
- The QWED Verification GitHub Action is maintained in its own repository —
QWED-AI/qwed-verification-action. It wraps theqwedai/qwed-verificationDocker image and is versioned independently of this release; it is not published from this repository, so no action release is part of v7.0.0.
Completes the Trust Boundary Completion epic — all 12/12 sub-issues closed. Every verification API pathway now returns DiagnosticResult and routes through enforce_trust_decision. The trust boundary is no longer advisory: the control plane requires and verifies attestation before admitting VERIFIED results, and VERIFIED is a protocol guarantee backed by a non-empty, deterministic proof_ref, never by execution, agreement, confidence, or provenance. Engine-level migrations to DiagnosticResult remain tracked under META #216.
⚠️ Breaking change:/verify/*API responses now use the unifiedDiagnosticResultschema (status /agent_message/developer_fields/proof_ref). Consumers of the previous ad-hoc dict responses must migrate.
- All
/verify/*endpoints returnDiagnosticResult(PR #276) - Control plane enforces mandatory attestation —
require_attestation=True, attestation issued + verified, enforced status drives HTTP response status (PR #278) - Batch math routes through
DiagnosticResult+ attestation +enforce_trust_decision(PR #282) - Attestation scope alignment — attest translated expression, not natural-language query, so
query_hashbinds to what was actually verified (#279, PR #285)
- ConsensusResult uses
DiagnosticStatusenum withproof_ref+verified_evidence(PR #280) - FactVerifier heuristic SUPPORTED verdict → UNVERIFIABLE with
advisory_checks(PR #283) - Consensus code execution advisory-only, VERIFIED → UNVERIFIABLE (PR #281)
- Consensus stats computation advisory-only, never VERIFIED (PR #277)
- LogicVerifier migrated to
DiagnosticResult(PR #262) - AgentStateGuard
proof_ref= real sha256 of committed bytes, not a static sentence (#268, PR #284)
- TOCTOU closure in
enforce_trust_decision—developer_fieldssnapshotted via recursive rebuild (nodeepcopyalias window), fail-closed snapshot (#273, PR #290) - Attestation signature verified before claim decode — silent generic error for all failure modes (#275, PR #287)
- Tenant-isolated verification cache —
VerificationCachekeys namespaced by normalizedtenant_id(#274, PR #286) - Unicode normalization in AgentStateGuard canonicalization — NFC collisions rejected (#272, PR #288)
- Mandatory proof artifact for VERIFIED attestations (issuance + consumption, PR #248)
- Credential / JWT / dockerignore security alerts resolved (PR #249)
- Math whitelist injection bypass removed (PR #251)
- Engine classification docs — Proof / Policy Enforcement / Advisory (PR #247)
QWED_RULES.mdcodifies the trust-boundary contract: #13 Separation of Responsibilities, #14 Verification Semantics, #15 Truth Before Policy; rules #7/#8 updated to capture admission-boundary and deterministic-proof semantics
qwed(PyPI):5.3.0->6.0.0qwed_sdk(Python):5.3.0->6.0.0@qwed-ai/sdk(NPM):5.3.0->6.0.0qwed(crates.io/Rust):5.3.0->6.0.0- API version marker:
5.3.0->6.0.0 - Kubernetes deployment image:
5.3.0->6.0.0 - Deployment docs + historical roadmap version references updated
#247docs: engine classification — Proof / Policy Enforcement / Advisory#248fix(#191): enforce mandatory proof artifact on VERIFIED attestations (issuance + consumption)#249fix: resolve credential / JWT / dockerignore security alerts#251fix(#227): remove math whitelist injection bypass#260fix(#257): hybrid engine advisory-only — never VERIFIED without proof#261fix(#259): FactVerifier advisory-only#262feat(#252): LogicVerifier migrated to DiagnosticResult#276fix(api): migrate all /verify/* endpoints to return DiagnosticResult (#264)#277fix(#270): consensus stats advisory-only, never VERIFIED#278fix(#265): control plane trust enforcement mandatory#280fix(#266): ConsensusResult DiagnosticStatus enum + proof_ref + verified_evidence#281fix(#269): consensus code execution advisory-only#282fix(#271): batch math DiagnosticResult → proof_ref + attestation + enforce_trust_decision#283fix(#267): FactVerifier SUPPORTED → UNVERIFIABLE with heuristic advisory_checks#284fix(#268): AgentStateGuard proof_ref real sha256#285fix(#279): attest translated expression, not natural language query#286fix(#274): VerificationCache tenant isolation#287fix(#275): attestation verify-before-decode + silent generic error#288fix(#272): NFC-normalize AgentStateGuard canonicalization#289fix: mock network in secret redaction tests (CI)#290fix(#273): close TOCTOU in enforce_trust_decision
SymbolicVerifier is the first fully DiagnosticResult-conformant verification engine and serves as the reference implementation for future engine migrations. The unified diagnostic model is no longer aspirational — one of 13 engines now demonstrates the complete pattern.
- Phase 1 — 6 public methods migrated to
DiagnosticResult:verify_code,verify_function_contract,verify_safety_properties,verify_bounded,analyze_complexity,get_verification_budget - Phase 2 — All internal code paths produce
AdvisoryCheckfor non-proof-bearing analysis;developer_fieldsprovides structured evidence;verification_modefield tracks bounded vs. unbounded analysis - Fail-closed math bugs (#129-#131) — All three resolved, ensuring safety constraints always block when out of budget (PRs #217-#219)
- Key rotation (#224) — Secure key attestation rotation implemented (PR #232)
qwed(PyPI):5.2.0->5.3.0qwed_sdk(Python):5.2.0->5.3.0@qwed-ai/sdk(NPM):5.2.0->5.3.0qwed(crates.io/Rust):5.2.0->5.3.0- API version marker:
5.2.0->5.3.0 - Kubernetes deployment image:
5.2.0->5.3.0
- 1 of 13 engines conformant — SymbolicVerifier as reference implementation
- Remaining engines tracked under META #216 (12 engines + security hardening + attestation consumption)
- Open audit issues: #162-#164 (Logic/Graph/Reasoning), #205 (SecureCodeExecutor), #221-#231 (security hardening), #191 (attestation consumption)
Core: SymbolicVerifier Migration (Phase 1 + Phase 2)
#212feat: migrate SymbolicVerifier to DiagnosticResult (Phase 1)#239feat: add verification_mode to SymbolicVerifier DiagnosticResults (#237)#240feat(#236): migrate verify_bounded to return DiagnosticResult#241feat(#234): migrate get_verification_budget to return DiagnosticResult#242feat(#233): migrate analyze_complexity to return DiagnosticResult#243feat(#235): migrate verify_safety_properties to return DiagnosticResult
Fail-Closed Bug Fixes (Math)
#217fix(math): fail-closed on ambiguous mode — block multi-mode datasets (#129)#218fix(math): require eigenvalue cardinality match before verification (#130)#219fix(math): require IRR convergence proof before VERIFIED (#131)
Security & Key Rotation
#220fix: remove unused check_assertions parameter from verify_code#232fix: use PBKDF2 instead of raw SHA-256 for key rotation hashing
Code Quality & Tooling
#208docs: archive stale docs — roadmap.md, ARCHITECTURE.md (historical), update DEPLOYMENT.md version refs#209docs: sync README with v5.2.0 codebase — engines, guards, architecture#210fix: Potential fix for code scanning alert no. 515: Log Injection#211fix: replace polynomial regex with O(n) str.find loop for data URI removal#213fix: silence CodeQL clear-text-logging false positives in security demo#215Add GitLab badge to README
Establishes the unified 3-layer DiagnosticResult model — the diagnostic contract that all verification engines will conform to. This is an additive release: no existing engine return types are changed. Engine conformance is tracked in blocked issues (#129, #130, #131, #133, #134, #162, #163, #164, #190, #205).
Three disclosure layers:
- Layer 1 — Agent-Safe:
agent_message: str— agent/model-facing summary, no internals leaked - Layer 2 — Developer:
developer_fields: dict— structured evidence (constraint_id, advisory_checks, methods_used, evidence) - Layer 3 — Proof:
proof_ref: Optional[str]— sha256 hash of retained proof artifact; the authority bit
Key design:
DiagnosticStatus: tri-state only (VERIFIED/UNVERIFIABLE/BLOCKED) — no proliferationproof_refis the authority bit: present = admissible for control flow, None = rejectVERIFIEDrequiresproof_ref— structurally enforced in__post_init__AdvisoryCheck: non-proof-bearing analysis (LLM fallback, NLI, VLM) —advisory_only=Trueenforcedcompute_proof_ref(): deterministic sha256 hashing of JSON-serialized evidencefrom_legacy_dict(): migration helper for ad-hoc engine dicts (fail-closed states only)- Both
DiagnosticResultandAdvisoryCheckarefrozen=Truedataclasses — prevents post-construction bypass
qwed(PyPI):5.1.2->5.2.0qwed_sdk(Python):5.1.1->5.2.0@qwed-ai/sdk(NPM):5.1.2->5.2.0qwed(crates.io/Rust):5.1.2->5.2.0- API version marker:
5.1.2->5.2.0 - Kubernetes deployment image:
5.1.2->5.2.0
- 83 new tests covering status taxonomy, all 3 layers, authority contract, fail-closed enforcement, advisory checks, proof hashing, serialization round-trip, legacy migration, frozen dataclass immutability, and realistic scenarios drawn from the 10 blocked issues.
#206feat(diagnostics): unified 3-layer DiagnosticResult model (#204)
Emergency patch fixing a High severity (CVSS 8.8) authenticated RCE vulnerability in SymPy parse_expr() across all math verification paths.
- CWE-95 mitigation: Added
safe_parse_expr()wrapper with denylist, stripped__builtins__, allow-listed math namespace, per-call global dict copy, and post-parse validation. Replaced all 17 directparse_expr()call sites inmain.py,verifier.py,batch.py, andvalidator.py. - Symbol consistency: Added
get_safe_symbol()to ensure calculus variables (n, Greek letters) match special SymPy assumptions, preventing incorrectdiff/integrate/limitresults. - Defense-in-depth: Pre-parse AST depth limit, post-parse SymPy tree depth validation,
sympy.Exprtype enforcement,extra_symbolskey/value validation, and sanitized exception handling.
- Cache Redis fail-closed: Enforced fail-closed Redis backend for distributed cache mode (PR #199).
- Benchmarks CI: CodSpeed performance benchmark workflow added (PR #198).
- TS SDK lockfile: Restored
package-lock.jsonfor reliablenpm ciin publish workflow (PR #197).
#197fix(ts-sdk): lockfile restore for npm ci publish#198ci: CodSpeed performance benchmarks#199fix(cache): fail-closed Redis backend for distributed mode#200fix(math): restrict sympy expression parsing (CWE-95)
Patch release packaging the post-v5.1.0 trust-boundary and fail-closed corrections into a coherent publishable state across core package metadata, SDKs, deployment references, and release automation.
- Cache trust-context binding: Bound verification cache artifacts to provider/model/policy/session trust context to prevent cross-context replay.
- Attestation hardening: Strengthened attestation verification with fail-closed behavior and follow-up review remediations.
- Audit integrity improvements: Tightened audit logging semantics around malformed payload handling, organization isolation, and transactional durability.
- Proof-path corrections: Refined reasoning, symbolic, batch, and agent-service fail-closed behavior where proof prerequisites or safe defaults were ambiguous.
- Version propagation: Aligned core package, API version marker, Python SDK metadata, TypeScript SDK metadata, and Rust SDK crate version on
5.1.1. - Container reference alignment: Updated Kubernetes deployment example to the published Docker Hub image/tag convention.
- Release metadata cleanup: Prepared package metadata and deployment references for a clean
v5.1.1publish flow.
#157docs: README follow-up#158fix(docker): python 3.13 upgrade follow-up#159chore(deps): npm/yarn dependency follow-up insdk-ts#160fix(schema): strict additional-properties enforcement follow-up#161fix(symbolic): fail closed when no proof exists#168fix(executor): secure executor fail-closed follow-up#176fix(agent): deny and handle unknown agent actions safely#177fix(reasoning): require proof prerequisites before reasoning acceptance#178and#192fix(cache): bind verification cache keys to trust context and address review follow-ups#179fix(audit): fail-closed audit logging, chain isolation, and transaction hardening#180fix(batch): separate batch math simplification from proof path#186chore(deps): pip dependency maintenance#193fix(tests): test-secret cleanup and PowerShell encoding hygiene
- Deployments using the Kubernetes example should pull
docker.io/qwedai/qwed-verification:5.1.1instead of the olderghcr.io/qwed-ai/qwed-corereference. - This patch release focuses on stricter semantics, release consistency, and fail-closed enforcement rather than end-user feature expansion.
Minor release expanding QWED from action verification into state governance while closing the adversarial fail-open gaps identified after v5.0.0. This release includes AgentStateGuard plus a focused hardening wave across execution, tool governance, mathematical verification, API semantics, and schema validation.
- AgentStateGuard: Added deterministic state verification with strict structural validation, semantic transition checks, and governed atomic state commits. This extends QWED from action-only verification to state and memory governance.
- Legacy CodeExecutor hard-blocked:
CodeExecutor.execute()now raisesRuntimeErrorunconditionally. All supported execution remains onSecureCodeExecutor. - Unknown tools default-denied:
ToolApprovalSystemnow blocks unknown tools regardless of heuristic risk score. - Bounded math tolerance:
verify_math()rejects oversized, negative, non-finite, and malformed tolerances instead of letting callers weaken correctness checks. - Legacy logic path fails closed:
verify_logic_rule()now raisesNotImplementedErrorinstead of returningNone. - Identity sampling rejected:
verify_identity()now returnsBLOCKEDwhen numerical sampling matches but no formal proof exists. - Ambiguous math API rejected:
/verify/mathnow blocks ambiguous implicit-multiplication expressions instead of returningis_valid: true. - Schema uniqueness fail-closed:
SchemaVerifiernow emitsuniqueness_validation_errorwhenuniqueItemscannot be proven deterministically.
- Progress-aware doom loop guard: Added LOOP-004 state-aware replay protection for repeated actions on unchanged state.
- Security and infrastructure hardening: Incorporated follow-up hardening across configs, CI, and infrastructure.
- Stats verifier coverage expansion: Added edge-case coverage for the statistics engine.
- CodeQL and cleanup follow-ups: Merged syntax, test, and static-analysis cleanup work after the v5.0.0 boundary release.
CodeExecutoris no longer usable as a legacy execution path. Migrate any direct imports toSecureCodeExecutor.- Unknown tools now require explicit allowlisting and are no longer auto-approved at low heuristic risk.
verify_math()may returnBLOCKEDfor tolerances that exceed the deterministic policy bound.verify_logic_rule()no longer returns an ambiguous non-result; callers must migrate toLogicVerifier.- Sampling-only
verify_identity()matches now returnBLOCKED, notUNKNOWN. - Ambiguous
/verify/mathexpressions now returnBLOCKEDwithis_valid: false. uniqueItemsvalidation failures are now explicit schema errors instead of silent passes.
qwed(PyPI):5.0.0->5.1.0qwed_sdk(Python):5.0.0->5.1.0@qwed-ai/sdk(NPM):5.0.0->5.1.0
#124feat(agent): add progress-aware doom loop guard (LOOP-004)#126security: harden configs, CI, and infrastructure -- full audit fixes#127test(stats): add edge case coverage for statistics engine#136fix(codeql): resolve remaining syntax and test cleanup alerts#137Update contributors section in README#139feat: AgentStateGuard - full implementation (structural + semantic + atomic commit)#149fix: hard-block legacy CodeExecutor execution path#150fix: default deny unknown tool approvals#151fix: bound verify_math tolerance by computed magnitude#152fix: fail closed in verify_logic_rule#153fix: fail closed in verify_identity#154fix: fail closed for ambiguous math api inputs#155fix: fail closed on uniqueItems validation errors
Major release focused on making QWED's verification boundary fail-closed, deterministic about what it proves, and substantially harder to bypass under adversarial conditions. Consolidates 98 commits and 20 merged PRs since v4.0.1, including the full PR 0–5 enforcement hardening series.
- Fail-Closed Verification: Disabled unsafe in-process execution fallbacks; stats and consensus paths now require secure Docker sandbox.
- Critical Boundary Closures: Removed logic verifier
eval()fallback — raisesRuntimeErrorifSafeEvaluatoris unavailable (CVE-QWED-001). - Mandatory Guards: Agent security guards (Exfiltration, MCP Poison) are now server-enforced and unconditional —
security_checksfield removed from request model. - Consensus Rate Limiting:
/verify/consensusendpoint now enforcescheck_rate_limitto prevent cost amplification attacks. - Self-Attestation Fix: Consensus fact engine no longer calls
verify_fact(query, query)— requires external context. - Redis Fail-Closed:
RedisSlidingWindowLimiternow denies requests on Redis errors instead of allowing them. - Timing-Safe Token Verification: Agent token comparison switched to
hmac.compare_digest. - Metrics Access Control:
/metricsand/metrics/prometheusnow require authenticated admin access. - Environment Integrity: Startup enforces
verify_environment_integrity()before database initialization.
- Natural-language math responses now return
INCONCLUSIVEwhen verifying LLM-translated expressions — neverVERIFIED. - Added explicit
trust_boundarymetadata in API responses describing what was actually verified. verify_identity()numerical sampling fallback now returnsUNKNOWNinstead ofLIKELY_EQUIVALENT.- Heuristic/non-proof outcomes are honestly labeled instead of presented as formal verification.
- Action context mandatory:
verify_action()requiresActionContextwithconversation_idandstep_number. - Replay detection: Same
(conversation_id, step_number)pair blocked (QWED-AGENT-LOOP-002). - Loop detection: Same action repeated 3+ times triggers DENIED (QWED-AGENT-LOOP-003).
- In-flight step reservations: Prevents race conditions in concurrent agent calls.
- Budget denial isolation: Budget-exceeded denials do not consume conversation state.
- Added
QWED_RULES.md— canonical enforcement contract for contributors and tools. - Added
.github/copilot-instructions.md— blocks Copilot from suggesting fallback execution. - Added
.github/pull_request_template.md— mandatory enforcement checklist. - Extended
.coderabbit.yamlwith enforcement-specific review instructions.
- Pinned third-party GitHub Actions to verified commit SHAs.
- Merged security autofix PRs and dependency hardening (#100–#114).
qwed(PyPI):4.0.1→5.0.0qwed_sdk(Python):2.1.0-dev→5.0.0@qwed-ai/sdk(NPM):4.0.1→5.0.0- TypeScript SDK: Removed
security_checksfrom agent verification helpers;tool_schemaremains.
test_pr115_regressions.py— critical boundary closures (eval removal, guard enforcement, consensus rate limit, fact self-attestation).test_pr117_regressions.py— stats fail-closed behavior, sandbox enforcement.test_pr4_runtime_hardening.py— Redis fail-closed, agent loop controls, metrics auth, environment integrity.test_pr5_determinism_alignment.py— trust boundary metadata, INCONCLUSIVE status, numerical sampling UNKNOWN.- Sanity sweep: 162 passed, 11 skipped, 0 failures.
INCONCLUSIVEis now a distinct verification status — downstream consumers must handle it.BLOCKEDandUNKNOWNare explicit outcomes, not generic failures.- Agent integrations must provide
ActionContextwithconversation_idandstep_number. /metricsendpoints now require admin role — update monitoring integrations accordingly.
POST /verify/process: Glass-box reasoning process verifier — IRAC structural compliance and custom milestone validation with decimal scoring.- Agent Security Checks:
POST /agents/{id}/verifynow acceptssecurity_checks: { exfiltration, mcp_poison }to runExfiltrationGuardandMCPPoisonGuardbefore verification.
- Information Disclosure: Removed raw
str(e)from/verify/ragerror responses; exceptions logged viaredact_pii(), clients receive onlyINTERNAL_VERIFICATION_ERROR. (Sentry + CodeQL) - Symbolic Precision:
RAGVerifyRequest.max_drm_ratechanged fromfloat | str→strwithfield_validatorenforcing Fraction-compatible values.
verifyProcess(): Validates AI reasoning traces using IRAC or custom milestone lists.verifyRAG():maxDrmRatetype changed fromnumbertostringfor symbolic precision.verifyAgent(): ReturnsAgentVerificationResponse, payload aligned with backend schema. Agent IDs URL-encoded.- Type Fixes:
VerificationResultData.riskandrisk_levelseparated. AddedProcess,RAG,SecuritytoVerificationTypeenum.
test_api_phase17_endpoints.py— covers/verify/process,/verify/ragexception masking, and agent security check blocking.
- RAGGuard: Detects prompt injection, data poisoning, and context manipulation in RAG pipelines with IRAC-compliant reporting.
- ExfiltrationGuard: Prevents data exfiltration through AI agent tool calls by analyzing output patterns and destination validation.
- MCP Poison Guard: Detects poisoned or tampered Model Context Protocol (MCP) tool definitions before agent execution.
- Five rounds of security review and hardening (CodeRabbit + SonarCloud).
- SovereigntyGuard: Enforces data residency policies and local routing rules for compliance-sensitive deployments.
- ToxicFlowGuard: Stateful detection of toxic tool-chaining patterns across multi-step agent workflows.
- SelfInitiatedCoTGuard (S-CoT): Verifies self-initiated Chain-of-Thought logic paths for reasoning integrity.
- ProcessVerifier: A new class of deterministic verification — IRAC/milestone-based process verification with decimal scoring, budget-aware timeouts, and structured compliance reporting. Ensures AI-driven workflows follow deterministic process steps.
- Code Injection Prevention: Replaced all
eval()calls with AST-compiled execution (SonarCloud S5334). - Sandbox Escape Fix: Patched critical sandbox escape and namespace mismatch vulnerability.
- SymPy Injection Fix: Hardened symbolic math input parsing against injection attacks.
- Protocol Bypass Fixes: Fixed URL whitespace bypass and protocol wildcard bypass vulnerabilities.
- CVE Patches: Resolved CVE-2026-24049 (Critical, pip/wheel), CVE-2025-8869, and HTTP request smuggling (h11/httpcore).
- Snyk Remediation: Fixed all 19 Snyk Code findings across the codebase.
- CodeQL Remediation: Secured exception handling in
verify_logic,ControlPlane,verify_stats, andagent_tool_call.
- Pinned base image digests with hash-verified requirements.
- Non-root user execution with
gosu/runuser. - Inlined entrypoint script to fix exec format errors across platforms.
- Enforced LF line endings via
.gitattributesanddos2unix. - Automated Docker Hub publishing on release and main branch push.
- SBOM generation and Docker Scout vulnerability scanning.
- Sentry SDK: Integrated error tracking and monitoring.
- CircleCI: Added Python matrix testing pipeline.
- SonarCloud: Added code quality and coverage workflow.
- Snyk: Added security scanning workflow with SARIF output.
- Docker Auto-Publish: Automated image publishing to Docker Hub on every release.
- Added OpenSSF Best Practices badge (Silver level).
- Added Snyk security badge and partner attribution.
- Added Docker Hub pulls badge and dynamic BuildKit badge.
- Updated engine count from 8 to 11 across all documentation.
- Added Ecosystem Trust & Infrastructure section to README.
- ProcessVerifier: decimal scores, edge cases, IRAC long input, malformed data.
- Attestation edge cases and qwed_local execution tests.
- Logic exception handling and stats engine coverage.
- Secure executor Docker availability checks.
- CodeQL Remediation: Resolved 50+ alerts including ReDoS, Clear-text Logging, and Exception Exposure.
- Workflow Permissions: Enforced
permissions: contents: readacross all GitHub Actions (dogfood,publish,sdk-tests) to adhere to Least Privilege. - PII Protection: Implemented robust
redact_piilogic in all API endpoints and exception handlers.
- Snyk Attribution: Added Snyk attribution to README and Documentation footer for Partner Program compliance.
- API Stability: Fixed unhandled exceptions in
verify_logicandagent_tool_callendpoints.
- Optimization Engine (
verify_optimization): AddedLogicVerifiersupport for Z3'sOptimizecontext. - Vacuity Checker (
check_vacuity): Added logical proof to detect "Vacuous Truths".
- Dockerized GitHub Action: The main
qwed-verificationaction now runs in a Docker container.
- Updated
logic_verifier.pywith additive, non-breaking methods. - Replaced shell-based
action_entrypoint.shwith robust Python handleraction_entrypoint.py.