Ana içerik geç

POST /api/zsc/set

Create or replace a secret. The plaintext value is encrypted in memory (AES-256-GCM via zeqEncrypt), then upserted into zsc_secrets. If a row with name already exists, value_enc and value_iv are replaced and updated_at is touched — every call rotates the IV.

Auth

Admin cookie (zeq_admin) required.

Request

curl -H "Cookie: zeq_admin=$ADMIN_JWT" \
-H "Content-Type: application/json" \
-X POST https://YOUR-FRAMEWORK/api/zsc/set \
-d '{
"name": "STRIPE_SECRET_KEY",
"value": "sk_live_...",
"purposeTag": "payments",
"boundZid": "ZEQ-FOUNDATION",
"permissions": ["ZEQ07111111111"],
"expiresZeqond": 2289676900
}'

Body fields

FieldRequiredTypeNotes
nameyesstringVault key. Validate against your naming convention before sending.
valueyesstringPlaintext. Up to 65,536 bytes. The server never logs this.
purposeTagnostring | nullFree-form analytics label.
boundZidnostringOwning ZID. Default: "ZEQ-SYS".
permissionsnostring[]Additional ZIDs allowed to read. Filtered to strings server-side.
expiresZeqondnobigintAuto-rotation target. If absent, the secret will be picked up by the rotation daemon at the next default cadence (~18.6 h).

Response · 200 OK

{ "ok": true, "name": "STRIPE_SECRET_KEY" }

The response is intentionally terse — the plaintext is never echoed back, not even as a confirmation. If you need to verify the write, follow up with GET /api/zsc/info/:name.

Errors

StatuserrorCause
400name requiredEmpty/missing name.
400value must be a stringWrong type.
400value cannot be emptyZero-length string. Use DELETE instead.
400value too large (>64KB)Hit the 65,536-byte ceiling.
401unauthorizedAdmin cookie missing/invalid.
500INTERNAL_ERRORDB unreachable or encryption error.

Audit row

A successful set emits one audit_log row:

transition_type = "secret_set"
actor_zid = <the admin's ZID from the JWT>
payload_json = { name, purpose_tag, bound_zid, permissions, expires_zeqond, purpose: "created" | "updated" }
proof_digest = SHA-256(name | actor_zid | transition_id | "set")

If the row already existed, payload_json.purpose is "updated". First-time write is "created". See ZSC Audit Trail.