KV persistence and access control
When KV changes are written to maand.db, who can read/write which namespaces, and how purge/GC works.
Key reference and examples: namespaces.md ยท Index: README.md
Inspect:
maand cat kv
maand cat kv --jobs api --active
maand cat kv get --reveal secrets/job/api db_password
Namespace overview
| Namespace | Written by | Survives rebuild? | Notes |
|---|---|---|---|
maand/bucket |
build | yes (synced) | Global: bucket_id, jobs, active_jobs, port names |
maand/worker/<ip> |
build | yes | Worker metadata, labels, peers |
maand/worker/<ip>/tags/<key> |
build | yes | From workers.json tags |
maand/job/<job> |
build | yes (when job active) | Job metadata, version, rollout_order, workers |
maand/job/<job>/worker/<ip> |
build + deploy | yes (when alloc active) | Certs, peers, version |
vars/bucket |
build | yes | From bucket.conf |
vars/bucket/job/<job> |
build | yes (when job active) | From bucket.jobs*.conf |
vars/job/<job> |
build + hooks | yes | App config; not wiped on rebuild |
secrets/job/<job> |
hooks | yes | AES-256-GCM encrypted |
maand/prometheus |
build | yes (synced) | Scrape configs only โ alerts/runbooks/dashboards stay in job_files โ prometheus |
When a job is removed from the workspace, maand build tombstones vars/job/<job> and secrets/job/<job> automatically. While the job remains in the workspace, both namespaces are retained unless you pass --purge-secrets-kv and the job has no active allocations (removed = 0 and disabled = 0). Build-owned namespaces for jobs whose allocations are all removed are still purged each build; maand gc purges remainder. See cli/gc.md.
Who can read which namespaces
Hooks and templates on allocation (job, worker_ip) may read:
maand/bucket,vars/bucketmaand/worker,maand/worker/<ip>,maand/worker/<ip>/tagsmaand/job/<job>,vars/bucket/job/<job>,vars/job/<job>,secrets/job/<job>maand/job/<job>/worker/<ip>- Upstream jobs in command demands:
maand/job/<upstream>,vars/job/<upstream>,secrets/job/<upstream>
maand cat kv --jobs <job> lists the same union across all non-removed allocations.
Writes from hooks are limited to vars/job/<current job> and secrets/job/<current job>. Full matrix: hook-api.md.
Persistence timing
| Context | When writes hit maand.db |
|---|---|
maand build |
End of main transaction; post_build hooks persist in a follow-up transaction |
maand deploy |
After each job's pre_deploy and after each deployJob (KV checkpoint) |
maand hooks |
On successful CLI exit |
maand health_check |
Read-only (mutations rejected) |
Deploy checkpoints roll back if the deploy transaction aborts before commit. Partial deploy commits KV for successful jobs.
Version history
KV keeps multiple versions per key. maand gc --retain-days N trims deleted history. Latest active keys: maand cat kv --active.
Key TTL
Hooks may set an optional ttl (seconds) on PUT /kv and /kv/secret. 0 or omitted means the key does not expire.
| Phase | Behavior |
|---|---|
| Write | Stores ttl and created_date (Unix seconds) on the new version row |
maand build |
Tombstones keys where created_date + ttl <= now (skipped for keys changed in the same build) |
maand gc |
Purges tombstoned rows and old version history per --retain-days (unchanged) |
Build-synced namespaces (maand/*, vars/bucket/*, workspace vars.conf keys) always write ttl = 0. TTL applies mainly to runtime-written vars/job/<job> and secrets/job/<job> keys.
Example (Python):
maand.put_job_variable("session_token", token, ttl=3600) # expire after 1 hour; tombstoned on next build after expiry
Between builds, an expired key remains readable until maand build runs. After tombstone, Get and hook reads treat the key as missing.
Related
- namespaces.md โ keys, examples, cookbook
- hook-api.md
- templates.md
- cli/build.md