Skip to main content

Human-in-the-loop approval workflows: policy rules, request lifecycle, peer pairing codes

Project description

nodus-approvals

Human-in-the-loop approval workflows for Nodus AI systems.

Policy-driven action gating with auto/deny/require/pairing modes, a full request lifecycle, and cryptographic peer-pairing codes. No required external dependencies — pure stdlib.

Status: v0.1.0 — prepared, not yet published.


Install

pip install nodus-approvals

What it provides

Component Purpose
ApprovalPolicy / ApprovalRule fnmatch-pattern rules; first match wins
ApprovalRequest / ApprovalResult Pending action + decision record
InMemoryApprovalStore Thread-safe request storage
ApprovalGate check / approve / deny / poll lifecycle
PairingStore / generate_code 6-digit code exchange for peer pairing

Quick start

from nodus_approvals import ApprovalGate, ApprovalPolicy, ApprovalRule, ApprovalMode

policy = ApprovalPolicy(rules=[
    ApprovalRule(action_pattern="admin.*", mode=ApprovalMode.REQUIRE),
    ApprovalRule(action_pattern="read.*",  mode=ApprovalMode.AUTO),
    ApprovalRule(action_pattern="*",       mode=ApprovalMode.DENY),
])

gate = ApprovalGate(policy=policy)

result = gate.check("read.memory", requester_id="u1")
# result.approved == True  (matched AUTO rule)

result = gate.check("admin.delete", requester_id="u1")
# result.approved == False, result.pending == True  (REQUIRE — needs human)

gate.approve(result.request_id, approver_id="admin-1")

Approval modes

Mode Behaviour
AUTO Immediately approved; no human required
DENY Immediately denied
REQUIRE Creates a pending ApprovalRequest; blocks until approved or denied
PAIRING Requires a valid pairing code exchange before approval

ApprovalPolicy

Rules are evaluated in order; the first matching rule wins. Patterns use fnmatch* matches any sequence, ? matches one character.

policy = ApprovalPolicy(rules=[
    ApprovalRule("payments.*",  ApprovalMode.REQUIRE, approver_ids=["finance"]),
    ApprovalRule("reports.*",   ApprovalMode.AUTO),
    ApprovalRule("*",           ApprovalMode.DENY),
])

policy.evaluate(action) returns the matching ApprovalRule (or the default DENY rule if no pattern matches).


ApprovalGate

gate = ApprovalGate(policy=policy, store=my_store)  # store defaults to InMemory

result = gate.check("some.action", requester_id="u1", context={"key": "val"})
# result.approved  — True/False
# result.pending   — True if REQUIRE mode and awaiting human decision
# result.request_id — present when pending

gate.approve(request_id, approver_id="approver-1", reason="looks good")
gate.deny(request_id,    approver_id="approver-1", reason="not authorised")
gate.poll(request_id)    # ApprovalResult | None — check current decision

Pairing codes

from nodus_approvals import PairingStore, generate_code

store = PairingStore(code_length=6, ttl_seconds=300)
code = store.issue(peer_id="peer-abc")        # e.g. "847291"
entry = store.validate(code)                   # PairingEntry | None
store.approve(code, approver_id="admin-1")    # mark as approved

generate_code(length=6) produces a cryptographically random numeric code. Expired entries are automatically excluded from validate.


InMemoryApprovalStore

from nodus_approvals import InMemoryApprovalStore, ApprovalRequest

store = InMemoryApprovalStore()
req = ApprovalRequest(action="admin.delete", requester_id="u1")
store.save(req)
store.get(req.id)
store.list_pending()
store.list_by_requester("u1")

Design

  • No required dependencies. Pure stdlib (fnmatch, secrets, threading, dataclasses, datetime, uuid).
  • Thread-safe. InMemoryApprovalStore and PairingStore use threading.Lock.
  • Pluggable storage. Any class satisfying the ApprovalStore protocol works.

Development

pip install -e ".[dev]"
pytest tests/ -q

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nodus_approvals-0.1.0.tar.gz (11.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nodus_approvals-0.1.0-py3-none-any.whl (10.3 kB view details)

Uploaded Python 3

File details

Details for the file nodus_approvals-0.1.0.tar.gz.

File metadata

  • Download URL: nodus_approvals-0.1.0.tar.gz
  • Upload date:
  • Size: 11.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for nodus_approvals-0.1.0.tar.gz
Algorithm Hash digest
SHA256 35452b0f75d4bf303d6556bca2a2e1547f4162a18ceb285c11bb10fb2b6ca681
MD5 f82704cc75984f290c4a2c8bda84e894
BLAKE2b-256 3639447311de07cba183a1b26df0e3302df376a30423c9348d5f7d47e21e8d2f

See more details on using hashes here.

File details

Details for the file nodus_approvals-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for nodus_approvals-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8b239786c1135214fdb6a31be3937e013e93a04aa634f00398437f4922ec67e4
MD5 be453850e86ee30aa183a007c97a3299
BLAKE2b-256 65937f3c38568c97c29adea0d68867a60fa23e81865160f831e9e0a46e080bc1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page