Perfect. I reviewed the OCaml JSON skill and your codebase constraints, and here is the official orchestration specification for this work (plan-only, no edits performed).
Spec ID
KEYZ-META-SYNC-001
- Status:
Planned
- Scope: provider key metadata sync, sidebar/details integration, pass-store sidecar metadata, git-safe workflow, HTTP integration, reliability/safety controls.
Decisions Locked
- Metadata is plaintext and git-versioned.
- Metadata lives inside the password-store repo, but outside encrypted
.gpg entries.
- Prefer
yojson (acceptable per your direction) over jsont for now.
- Keep secret values encrypted in pass only; never copy secrets into metadata files.
- Default behavior is safe/non-destructive: no automatic commit, no provider writeback unless explicitly enabled per provider capability.
Filesystem Layout (Password Store)
- Root:
$PASSWORD_STORE_DIR
- New sidecar root:
$PASSWORD_STORE_DIR/.keyz/
- Layout:
.keyz/providers/registry.json (key-to-provider mapping, aliases, env-var names, capabilities cache)
.keyz/providers/<provider>/<account_or_team>/<key_alias>.json (latest normalized metadata snapshot)
.keyz/providers/<provider>/<account_or_team>/<key_alias>.history.jsonl (append-only sync history, optional)
.keyz/state/sync_state.json (last run, backoff, per-provider health)
- Rationale:
.keyz is hidden and already ignored by current pass tree scan behavior (dot dirs are skipped), so UI must join metadata to visible key nodes programmatically.
Data Model (Strongly Typed OCaml)
- Add
src/key_metadata.ml/.mli:
provider_id, account_ref, key_alias, key_path
balance_usd option, credits_total option, credits_used option
usage_window, cost_window, expires_at option
sync_status = Live | Stale | Error
last_sync_at, last_success_at, last_error
capabilities = { can_read_balance; can_read_usage; can_read_cost; can_write_billing }
schema_version
- Add
src/provider_types.ml/.mli:
- normalized request/response records per provider family
- typed error taxonomy (
Auth_error | Rate_limited | Parse_error | Network_error | Provider_error).
JSON Handling Plan
- Add dependency:
yojson.
- Parsing approach:
- Phase 1: resilient manual field extraction with explicit defaults and
option fields.
- Strictly ignore unknown fields.
- Preserve raw provider payload hash for audit/debug (not full payload by default).
- Serialization:
- deterministic key order, stable formatting, UTC timestamps.
- schema version on every metadata document.
- Migration:
schema_version checked on load; migration stubs included from v1 onward.
Provider Integration Plan
- Add
src/provider_registry.ml/.mli:
- capability map and endpoint descriptors per provider.
- Add
src/provider_clients.ml/.mli:
- read-only first:
xai, openrouter, deepseek, cloudflare, anthropic, github, openai, google, moonshot, zai, cerebras.
mistral marked unsupported until verified endpoint spec.
- Add
src/credential_resolver.ml/.mli:
- resolve from pass key path mapping + env var names in registry.
- never persist resolved secret values.
- Add
src/http_client.ml/.mli:
- typed HTTP wrapper, timeout/retry/backoff/jitter, status handling, rate-limit parsing.
HTTP Request/Response Reliability Rules
- Request safety:
- hard timeouts, bounded retries, exponential backoff with jitter.
- provider-specific concurrency caps.
- Response safety:
- validate status + content-type.
- parse failures become typed errors; no crashes.
- partial success handling for multi-key/provider batch sync.
- Observability:
- per-provider counters: success, stale, fail reason buckets.
- UI-safe status strings only (no secrets).
Pass Integration
- Continue using existing pass scanning for secret entries only.
- Metadata is joined by
key_path/alias mapping:
- key node remains sourced from pass tree.
- metadata is loaded from
.keyz/providers/... and merged at render time.
- Copy behavior (
p) unchanged for secrets.
- Metadata actions do not require decrypting secret body unless provider auth derivation needs explicit key lookup.
UI/UX Integration (Sidebar + Details)
src/ui_tree.ml updates:
- per-node badge/state from metadata:
live, stale, error, low.
- optional mini-value for balance/credits on provider-relevant entries.
src/ui_details.ml updates:
- “Provider Metadata” block with last sync, balance/usage/cost summary, capability display.
- actions:
r: sync selected key metadata
R: sync provider/account subtree
a: toggle autosync mode
u: update remote metadata/billing only if capability + explicit enable.
src/main.ml updates:
- status bar help for new keys
- background sync fibers + safe status notifications.
Hooks and Triggers
- Runtime triggers:
- periodic autosync (default on, conservative interval)
- selection-triggered sync if stale and debounce window elapsed
- manual sync keybindings
- Optional orchestrator hooks:
- startup warm sync (small batch)
- explicit command mode later (
toki sync --provider xai).
- No destructive git hooks. No automatic push.
Git Strategy
- Metadata sidecars are git-tracked in same repository as keys.
- Default: write files only; user controls commit timing.
- Optional mode: stage metadata automatically (no commit).
- Optional mode: auto-commit metadata with guarded message template.
- Commit safety:
- never stage secrets outside intended paths automatically.
- never rewrite history; no force operations.
- detect dirty tree and isolate metadata staging pathspecs.
Security and Safety Constraints
- Never store plaintext API secrets in
.keyz.
- Never include auth headers/tokens in logs/status/history.
- Provider write/update endpoints disabled by default.
- All provider mutations require capability allowlist + explicit user action.
- Keep last known good metadata when sync fails (avoid blanking state).
- Distinguish stale-vs-error in UI to avoid misleading operators.
Implementation Work Packages (for Orchestrator)
- WP1: Types + schema + registry scaffolding.
- WP2: Sidecar storage reader/writer (
.keyz), deterministic JSON format.
- WP3: HTTP client wrapper + retry/backoff + error typing.
- WP4: Provider read-only clients (priority: xAI/OpenRouter/DeepSeek/Cloudflare).
- WP5: Sync engine (manual + periodic + selection triggers).
- WP6: UI integration (tree badges, details panel actions, status line).
- WP7: Git integration mode flags (none/stage/commit).
- WP8: Tests (parsing, mapping, sync state machine, UI state projection, git path safety).
Testing and Verification
- Unit:
- parser resilience for each provider sample payload
- schema roundtrip and migration
- sync status transitions and stale TTL logic
- Integration:
- mocked HTTP providers (200/401/429/500/timeout)
- sidecar write/read consistency
- no-secret leakage assertions
- UI:
- badge rendering from metadata states
- action keypaths call proper sync routines
- Git:
- stage pathspec correctness
- no accidental staging outside
.keyz.
Acceptance Criteria
- Selected key nodes show provider metadata state in sidebar.
- Details pane supports sync/update actions with clear feedback.
- Metadata persists in
.keyz sidecars, tracked by git.
- Autosync works with bounded retries and safe degradation.
- No secrets are written to metadata or logs.
- Strongly typed error handling prevents crashes on malformed/partial provider responses.
Notes on OCaml Skill Use
- I reviewed the
jsont skill; we will not depend on it for this phase.
- This spec adopts
yojson + typed adapters as requested, with room to migrate later if needed.
If you want, next I can produce the execution-ready orchestrator task graph (agent-by-agent prompts and exact file touch list) so implementation can start immediately.