feat(sign): structured policy decisions + English-only locales (0.0.3)#14
Conversation
…ly locales sign_action now returns a structured authorized decision instead of raising on a 403. A permitted action returns authorized=true with the signature receipt (now including signature_b64); a policy block, emergency halt, delegation limit, or quarantine returns authorized=false with a machine reason and human detail so a Dify workflow can branch on the decision. Policy blocks also pass through the signed denial receipt (signed_deny). Also removes the untranslated zh_Hans and pt_BR locale keys (they duplicated the English strings) so user-facing text is English-only across manifest, provider, and tools. Bumps manifest to 0.0.3 and adds 403-path smoke tests.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8364ae7266
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if response.status_code == 403: | ||
| yield self.create_json_message(_denied_result(response)) |
There was a problem hiding this comment.
Only swallow recognized policy 403 responses
When the sign endpoint returns a generic 403 that is not one of the policy-decision shapes (for example a forbidden agent/API-key scope issue or an upstream HTML/WAF 403), this branch now converts it into authorized: false with a default policy-denial detail instead of raising as the previous raise_for_status() path did. That makes operational/auth failures look like branchable action denials, so workflows can silently take the wrong path; this should only return a denial object after validating the response body matches a known refusal shape, and otherwise let the HTTP error propagate.
Useful? React with 👍 / 👎.
… outputs Adds output_schema (JSON-Schema) to sign_action, verify_signature, and request_action so each returned key (authorized, signature_id, verified, etc.) becomes an addressable workflow variable. Without this, a Dify workflow can only read the tool's text/json/files, not individual fields. No Python change: the existing create_json_message dict maps 1:1 to the declared properties. Also extends .difyignore to exclude tests, CI config, caches, and the local venv so the packaged plugin is clean.
- README documents the structured authorized decision, signature_b64, and the full output of all three tools (was stale on Sign Action). - sign_action timestamp schema corrected to a Unix epoch number (cloud returns a float, not an ISO 8601 string). - Capitalised the display label and credential prose to Asqav across the manifest, provider, and tool definitions. - .difyignore now excludes the worktree .git link file so it stops leaking into the packaged plugin. - CHANGELOG records the output_schema, README, and schema-fix changes.
… at runtime
A Dify tool node only exposes text/files/json by default; a single
create_json_message leaves named selectors like {{#node.signature_id#}}
unresolved at runtime even with output_schema (which only feeds the editor
picker). Each tool now also emits one create_variable_message per field via a
shared _outputs.emit helper, so workflow nodes can address every field by name.
Updates smoke tests to assert the JSON message plus per-field variables.
What
sign_actionnow returns a structured authorized decision instead of raising on a refusal, so a Dify workflow can branch on the outcome.authorized: truewith the signature receipt, now includingsignature_b64(the tamper-evident artifact) alongsidesignature_id,action_id,timestamp, andverification_url.authorized: falsewith a machinereason(policy_blocked,emergency_halt,delegation_denied,quarantine, ordenied) and a human-readabledetail. A policy block also passes through the signed denial receipt (signed_deny), which is itself verifiable.This makes the kill-switch and policy-gate behavior usable in a workflow: a halted organization or a blocked action becomes branchable data instead of an opaque error.
Also in this release (0.0.3)
en_US). Removed the untranslatedzh_Hansandpt_BRlocale keys that duplicated the English strings across the manifest, provider, and tool definitions.Verification
{error: action_denied, attestation_hash, signed_deny}for policy and content blocks;signature_b64is a real field on the sign response.request_actionandverify_signatureare unchanged.