audit-1 (critical 1): mandatory operator signatures bound to content+deployment
- signing module: canonical content hashes + approval_message sha256(cayce-ops:<type>:<deployment_id>:<id>:<content_hash>) - approve/approve-draft/publisher-approve REQUIRE signature; without CAYCE_OPS_OPERATOR_PUBKEY+DEPLOYMENT_ID the daemons refuse to execute/send/publish (no degraded mode) - run-time re-verification at execute/send/publish: unsigned rows (raw SQL approval) or edited content revert to pre-approval state, audited as error - FULL signatures stored on rows (operator_signature, migration 0003) and in audit detail — never truncated - signature failures audited from CLI wrappers too (1f) - AUTONOMOUS_MODE approval path removed (D13): no non-human approvals tests: SQL-approved row refused at execute/send/publish; to_addr change blocks send; foreign deployment/content signatures refused; full-signature persistence. 65 tests green.
This commit is contained in:
+30
-8
@@ -74,10 +74,10 @@ def executor_approve(
|
||||
proposal_id: int,
|
||||
actor: str = typer.Option(..., help="Human approver id"),
|
||||
signature: str = typer.Option(
|
||||
None, help="BIP-340 sig (required when operator pubkey is set)"
|
||||
..., help="BIP-340 sig over the approval message (mandatory)"
|
||||
),
|
||||
) -> None:
|
||||
"""Approve a proposal (human action, audited)."""
|
||||
"""Approve a proposal (human action, audited; signature mandatory)."""
|
||||
raise typer.Exit(
|
||||
_load_component("executor").approve(proposal_id, actor, signature=signature)
|
||||
)
|
||||
@@ -101,9 +101,17 @@ def maild_poll() -> None:
|
||||
|
||||
|
||||
@maild_app.command("approve-draft")
|
||||
def maild_approve(msg_id: int, actor: str = typer.Option(...)) -> None:
|
||||
"""Approve a drafted reply so SMTP may send it."""
|
||||
raise typer.Exit(_load_component("maild").approve_draft(msg_id, actor))
|
||||
def maild_approve(
|
||||
msg_id: int,
|
||||
actor: str = typer.Option(...),
|
||||
signature: str = typer.Option(
|
||||
..., help="BIP-340 sig over the approval message (mandatory)"
|
||||
),
|
||||
) -> None:
|
||||
"""Approve a drafted reply so SMTP may send it (signature mandatory)."""
|
||||
raise typer.Exit(
|
||||
_load_component("maild").approve_draft(msg_id, actor, signature)
|
||||
)
|
||||
|
||||
|
||||
@maild_app.command("send-approved")
|
||||
@@ -153,9 +161,17 @@ def publisher_image(item_id: int) -> None:
|
||||
|
||||
|
||||
@publisher_app.command("approve")
|
||||
def publisher_approve(item_id: int, actor: str = typer.Option(...)) -> None:
|
||||
"""Approve a draft content item."""
|
||||
raise typer.Exit(_load_component("publisher").approve(item_id, actor))
|
||||
def publisher_approve(
|
||||
item_id: int,
|
||||
actor: str = typer.Option(...),
|
||||
signature: str = typer.Option(
|
||||
..., help="BIP-340 sig over the approval message (mandatory)"
|
||||
),
|
||||
) -> None:
|
||||
"""Approve a draft content item (signature mandatory)."""
|
||||
raise typer.Exit(
|
||||
_load_component("publisher").approve(item_id, actor, signature)
|
||||
)
|
||||
|
||||
|
||||
@publisher_app.command("publish-due")
|
||||
@@ -187,6 +203,12 @@ def monitor_run() -> None:
|
||||
raise typer.Exit(_load_component("monitor").build())
|
||||
|
||||
|
||||
@monitor_app.command("anchor")
|
||||
def monitor_anchor() -> None:
|
||||
"""Publish today's audit-chain anchor as a signed Nostr note (1/day)."""
|
||||
raise typer.Exit(_load_component("monitor").anchor())
|
||||
|
||||
|
||||
def main() -> None: # pragma: no cover
|
||||
app()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user