AO-native command layer for Blackcat Darkmesh. This repository hosts the write-side AO processes that enforce idempotent, authorized, and auditable changes to the canonical state maintained in blackcat-darkmesh-ao. No separate server-side authority exists; any bridge or admin client is only a transport adapter.
- In scope: AO command processes, handlers, idempotency registry, audit/event emission, publish workflow (draft → review → publish → rollback), validators and schemas, minimal adapters, deploy/verify scripts, fixtures, CI workflows.
- Out of scope: read/state model (lives in
blackcat-darkmesh-ao), gateway rendering, frontend assets, secrets or signing keys.
- Role: command-first AO process set that owns write semantics, conflict detection, and append-only audit; delegates state materialization to
blackcat-darkmesh-ao. - Pipeline: command envelope → validation (schema + policy) → idempotency / anti-replay → handler → audit + event → downstream AO state update.
- Identity & auth: signed commands or capability tokens; gateway is never an implicit authority.
- Idempotence:
requestIdregistry and optimisticexpectedVersionguards to prevent duplicate writes. - Audit: append-only log with correlation to requestId and actor; deterministic status codes.
docs/ # command contracts, flows, failure modes, ADRs, runbooks
ao/ # AO command process and shared libs
write/ # command handlers, routing
shared/ # auth, idempotency, validation, audit
schemas/ # JSON schemas for command envelopes and actions
scripts/ # deploy | verify
fixtures/ # sample command envelopes and expected outcomes
tests/ # contract, conflict, and security tests
scripts/bridge/ # stub forwarder from write outbox to -ao
scripts/cli/ # local helpers (run command)
.github/workflows/ # CI entrypoint
- Required tags:
Action,Request-Id,Actor,Tenant,Expected-Version,Nonce,Signature-Ref,Timestamp. - Core handlers (initial set):
SaveDraftPage,PublishPageVersion,UpsertRoute,UpsertProduct,AssignRole,UpsertProfile,GrantEntitlement. - Conflict strategy: reject on missing/expired nonce, replayed
Request-Id, or mismatchedExpected-Version; return prior result when replayed.
- Prereqs:
lua5.4(orluac) andpython3. - Static checks:
scripts/verify/preflight.sh(JSON schema validation + Lua syntax). - Contract smoke tests:
LUA_PATH="?.lua;?/init.lua;ao/?.lua;ao/?/init.lua" lua5.4 scripts/verify/contracts.lua(or setRUN_CONTRACTS=1to run during preflight). - Conflict/security smoke tests:
LUA_PATH="?.lua;?/init.lua;ao/?.lua;ao/?/init.lua" lua5.4 scripts/verify/conflicts.lua(orRUN_CONFLICTS=1). - Batch fixtures:
LUA_PATH="?.lua;?/init.lua;ao/?.lua;ao/?/init.lua" lua5.4 scripts/cli/batch_run.lua(orRUN_BATCH=1in preflight) – compares fixtures to*.expected.json. - Branches:
main(releasable),develop(integration),feature/*,adr/*,release/*. - Message contracts and schemas are public API; prefer additive changes over breaking ones.
WRITE_REQUIRE_SIGNATURE=1— reject commands withoutsignatureRef.WRITE_REQUIRE_NONCE=1— reject commands without nonce and block replay.WRITE_NONCE_TTL_SECONDS(default 300) andWRITE_NONCE_MAX(default 2048) — nonce cache sizing.WRITE_ALLOW_ANON=1— allow missing actor/tenant (off by default).WRITE_SIG_TYPE=ed25519|ecdsa|hmac(prod default:ed25519);WRITE_SIG_PUBLIC(PEM) orWRITE_SIG_SECRET(hmac key) to verifysignature.- Optional JWT gate: set
WRITE_JWT_HS_SECRET(HS256) and optionallyWRITE_REQUIRE_JWT=1to fail-closed; claimssub/tenant/role/noncepopulateactor/tenant/role/noncewhen missing. WRITE_WAL_PATH=/var/lib/ao/write-wal.ndjson— append-only WAL with request/response hashes.WRITE_IDEM_PATH=/var/lib/ao/write-idem.json— persist idempotent responses across restarts (optional).WRITE_OUTBOX_PATH=/var/lib/ao/write-outbox.json— persist outbox events (used by forwarders/export).- Checksum watchdog:
ops/systemd/write-checksum.service+scripts/verify/checksum_daemon.sh(setWRITE_WAL_PATH,WRITE_OUTBOX_PATH,CHECKSUM_INTERVAL_SEC). - Resolver flags:
WRITE_FLAGS_PATH=/etc/ao/resolver-flags.ndjsonto block/readonly resolvers (shared with registry/AO); enforced before policy. - Shipping/Tax export for AO: persist rates with
WRITE_RATE_STORE_PATHand runscripts/export/rates.lua [rate_store] [shipping.ndjson] [tax.ndjson]; point AO to the outputs viaAO_SHIPPING_RATES_PATH/AO_TAX_RATES_PATH. - Dispute evidence payload:
AddDisputeEvidenceacceptsevidence.url|hash|hashAlgo|type|note|fileNameto carry provider links/hashes; stored inpayment_disputesand can be sent via provider webhooks. WRITE_RL_WINDOW_SECONDS/WRITE_RL_MAX_REQUESTS— rate-limit per tenant+actor (default 60s / 200 reqs).- Bridge/env for queue/HTTP:
AO_ENDPOINT=https://...(optional);AO_API_KEY;DRY_RUN=1orAO_BRIDGE_MODE=mock|off|http;AO_BRIDGE_RETRIES/AO_BRIDGE_BACKOFF_MS;AO_QUEUE_PATH(persisted queue),AO_QUEUE_LOG_PATH=/var/lib/ao/queue-log.ndjson,AO_QUEUE_MAX_RETRIES=5,AO_EXPECT_RESPONSE_HASHto enforce downstream body hash. - Trust manifest signing (resolvers): set
TRUST_MANIFEST_HMACand runlua scripts/cli/trust_manifest_sign.lua manifest.json > manifest.signed.json; optionally setTRUST_MANIFEST_SIGNER. - Key management: keep public keys under
/etc/ao/keys, record theirsha256sumin ops docs, rotate on a schedule; never store private keys in repos, artifacts, or CI logs. - OTP/passwordless:
OTP_TTL_SECONDS(default 300, min 30, max 3600),OTP_JWT_TTL_SECONDS(default 900) control IssueOtp/ExchangeOtp flow.
lua scripts/cli/run_command.lua ./fixtures/sample-save-draft.json— route a JSON command locally and print the response (uses in-memory state). A publish sample is atfixtures/sample-publish.json.RUN_BATCH=1 LUA_PATH="?.lua;?/init.lua;ao/?.lua;ao/?/init.lua" lua scripts/cli/batch_run.lua— run all fixtures and enforce matches to*.expected.json(CI uses this).- Queue forwarder (persisted outbox → HTTP):
AO_QUEUE_PATH=dev/outbox-queue.ndjson AO_QUEUE_LOG_PATH=dev/queue-log.ndjson AO_QUEUE_MAX_RETRIES=5 LUA_PATH="?.lua;?/init.lua;ao/?.lua;ao/?/init.lua" lua scripts/bridge/queue_forward.lua - Health snapshot (write-side files & deps):
WRITE_WAL_PATH=... WRITE_OUTBOX_PATH=... AO_QUEUE_PATH=... LUA_PATH="?.lua;?/init.lua;ao/?.lua;ao/?/init.lua" lua scripts/verify/health.lua
scripts/bridge/forward_outbox.luareads the in-memory outbox (write._storage_outbox()) and logs events you would forward toblackcat-darkmesh-ao. Replaceforward_eventwith signed POST to AO endpoint (registry/site process) in production.scripts/bridge/export_outbox.lua [outfile]dumps outbox to NDJSON (defaultdev/outbox.ndjson) for offline inspection or manual upload.scripts/bridge/forward_outbox_http.luaposts outbox events toAO_ENDPOINT(setDRY_RUN=1to log only; optionalAO_API_KEY,AO_SITE_IDtag).
- No secrets or raw keys in AO state, manifests, or adapters.
- Gateways act only as clients; write process re-validates auth and policy.
- All comments and docs remain in English.
Blackcat Darkmesh Write Proprietary License (see LICENSE). External contributions require written permission from Black Cat Academy s. r. o.