Skip to content

feat(sign): structured policy decisions + English-only locales (0.0.3)#14

Merged
jagmarques merged 4 commits into
mainfrom
feat/sign-policy-decisions
May 30, 2026
Merged

feat(sign): structured policy decisions + English-only locales (0.0.3)#14
jagmarques merged 4 commits into
mainfrom
feat/sign-policy-decisions

Conversation

@jagmarques

Copy link
Copy Markdown
Owner

What

sign_action now returns a structured authorized decision instead of raising on a refusal, so a Dify workflow can branch on the outcome.

  • Permitted action returns authorized: true with the signature receipt, now including signature_b64 (the tamper-evident artifact) alongside signature_id, action_id, timestamp, and verification_url.
  • Refused action returns authorized: false with a machine reason (policy_blocked, emergency_halt, delegation_denied, quarantine, or denied) and a human-readable detail. A policy block also passes through the signed denial receipt (signed_deny), which is itself verifiable.
  • Other non-2xx responses (auth, quota, server) still raise, so real faults stay loud.

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)

  • User-facing text is now English-only (en_US). Removed the untranslated zh_Hans and pt_BR locale keys that duplicated the English strings across the manifest, provider, and tool definitions.
  • Manifest bumped to 0.0.3.
  • Added smoke tests for the 403 decision paths (string-form and signed-deny dict-form). 19/19 pass; ruff clean.

Verification

  • The decision shapes were confirmed against the live cloud sign path: string-form refusals for emergency halt, delegation, and quarantine; dict-form {error: action_denied, attestation_hash, signed_deny} for policy and content blocks; signature_b64 is a real field on the sign response.
  • request_action and verify_signature are unchanged.

…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.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread tools/sign_action.py Outdated
Comment on lines +46 to +47
if response.status_code == 403:
yield self.create_json_message(_denied_result(response))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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.
@jagmarques jagmarques merged commit a3e7beb into main May 30, 2026
1 check passed
@jagmarques jagmarques deleted the feat/sign-policy-decisions branch May 30, 2026 12:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant