Repository navigation
feat: add seeded snapshots, backups, secret rotation and CD - #162
Closed
thegreatfeez wants to merge 1 commit into
Closed
thegreatfeez wants to merge 1 commit into
thegreatfeez wants to merge 1 commit into
Conversation
- deterministic seed dataset with local IPFS, raw-event export and anonymised snapshots - checksummed backups, restore script and post-restore chain reconciliation - env/file/Vault secret loading with hot rotation and JWT grace - digest-pinned CD with migration lint and post-deploy checks closes OracleDesk#147 closes OracleDesk#146 closes OracleDesk#145 closes OracleDesk#144
|
@thegreatfeez Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
|
👋 Thanks for the contribution! This repository only accepts contributor pull requests into the Please re-open your PR with base: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
closes #147,
closes #146,
closes #145,
closes #144.
All four items from
issues.mdwere implemented inOracleDesk-Backend. Theseed/snapshot workflow is deterministic and self-verifying, backups have a
checksummed manifest and a restore-time chain reconcile, secrets load from
env/files/Vault and rotate without a restart, and the CD pipeline builds a
digest-pinned signed image with migration compatibility checks and post-deploy
verification.
issues.mditem#147 — Deterministic seed and anonymised snapshot
src/seed/scenario.tsbuilds a repeatable dataset from a fixed PRNG:45 markets across every category/status, 12 users, trades, positions, traces,
copy trades, subscriptions, payments, allowances, chain events, logs, signal
cache and generation jobs. Same seed → byte-identical output.
questionHashover the canonicalquestion document,
resolutionHashover the XDR spec, andtraceHashoverthe canonical trace payload. A test recomputes all three.
IPFS_TRANSPORT=localnow selects a disk-backed transport. Seeded questionand trace bytes are written under
.ipfs-local/<cid>using a dependency-freeCIDv1(raw, sha2-256). Config refuses
localin production.prisma/seed.tsrefusesNODE_ENV=production,CHAIN_EXECUTION_MODE=liveand non-local database hosts (unless
SEED_ALLOW_REMOTE=1). Re-runs useskipDuplicates;--resettruncates first.--now,--from-snapshot,--link-testnetand--with-raw-eventsare supported.--with-raw-eventsre-encodesTrade,MarketCreated,MarketResolvedandTracePublishedinto the recordedgetEventsshape; a test decodes everyencoded event with the contract spec.
scripts/snapshot-export.tswrites anonymised NDJSON.src/lib/snapshot.tsholds a fail-closed column allowlist (a new column stops the export), maps
wallet addresses to deterministic throwaway G-addresses, keyed-hashes tx
hashes, drops log payloads/errors and scans the output for secret patterns.
signal_cacheis explicitly excluded.prisma.config.tswirestsx prisma/seed.ts;npm run db:seedandnpm run snapshot:exportare inpackage.json.#146 — Backup/restore plus reconcile
scripts/backup.shtakes a custom-formatpg_dump,.sha256, and a manifestwith migrations, indexer cursor(s), max chain ledger, newest payment time and
row counts.
--critical-onlywrites NDJSON;--encrypt-touses age.Retention is controlled by
BACKUP_KEEP_DAILY/BACKUP_KEEP_WEEKLY.scripts/restore.shverifies the checksum, refuses a non-empty target unless--force, runspg_restore, appliesprisma migrate deployand prints themanifest.
src/services/reconcile.service.ts(CLI:scripts/post-restore-reconcile.ts) rewinds the cursor to the manifestboundary minus 720 ledgers, clamps to RPC retention and reports the gap,
calls
backfillEvents, re-projects every surviving event at/after theboundary, re-verifies CONFIRMED payments without aborting on retention loss,
checks every resolution preimage, and optionally reports unclaimed recipient
transfers. It exits non-zero only for missing/mismatched specs.
src/services/indexer.service.tsexportsreprojectEventanddecodedFromStored; trace-hash handling now accepts both Buffer and thehex form stored in Postgres.
.github/workflows/restore-drill.ymlseeds, backs up, drops the schema,restores, and reconciles against
tests/fixtures/events.jsonmonthly.docs/runbooks/backup-restore.md; Compose has an optionalbackupprofile.#145 — Secrets loading and hot reload
src/config/secrets.tsresolves<NAME>_FILE, validates at boot and refreshwith the same rules, stores raw values as Buffers, exposes
secret()/secretEntry()/previousSecret(), and refreshes on an interval withjitter. Empty or invalid refresh values keep the old value; provider failures
keep everything.
(token from a file, never the environment). The interface allows AWS Secrets
Manager to be added without touching consumers.
SECRETS_PROVIDER,SECRETS_REFRESH_MS,JWT_PREVIOUS_SECRET_GRACE_SECS,VAULT_*arevalidated in
src/config/index.ts.DATABASE_URL_FILEis resolved before Zod and inprisma.config.ts, so boththe app and Prisma CLI work with a mounted URL. It is set on the process
before the Prisma client is constructed.
the grace window, and never retries an expired token. The retired Buffer is
zeroed. Gemini and Anthropic clients rebuild when their key version changes;
IPFS and ingestion read at call time.
initSecretsandstartSecretRefresh; failure exits with thevariable named. Tests cover files, dual-source rejection, empty files, short
JWTs, immutable/empty/failed refreshes, previous-key acceptance and expiry,
and client rebuilds.
#144 — Continuous delivery
.github/workflows/cd.ymlverifies via CI, builds and pushes a digest,keylessly signs it with cosign, emits an SPDX SBOM, deploys staging then
production through the reusable
deploy-env.yml, and runs post-deploy checksafter each.
deploy-env.ymlverifies the cosign identity, lints only the migrationschanged in that release, applies
prisma migrate deploybefore Helm, andruns
helm upgrade --install --atomicby image digest. Secrets come fromGitHub Environments.
scripts/check-migration-compat.mjsflags drops, renames, type changes,SET NOT NULL, and non-concurrent indexes. Tests cover breaking and safe SQL;CI runs it for newly added migrations only (historical migrations predate the
rule).
scripts/post-deploy-checks.shrequires readiness to hold N consecutiveprobes, compares the deployed image digest with the release digest, checks
indexer lag and cursor advancement (status endpoint or Postgres + RPC), and
checks Prometheus critical alerts and 5xx ratio. Tests cover pass and
readiness failure.
/readyzwas added for readiness.docs/deployment.mddocuments the pipeline, migration direction and rollback.Verification
npm run buildnpm testnpx tsc --noEmit -p tsconfig.test.jsonsnapshot-export,post-restore-reconcile,prisma/seed) typechecknpx prisma validateactionlint .github/workflows/*.ymlshellcheck scripts/*.shLive Postgres/Redis were not available in this environment, so the seed write,
pg_dump/pg_restoreand the hosted workflows were exercised through unittests and mocks rather than an end-to-end run. The restore drill is wired to
run them in CI.
Judgement calls
issues.mdtargetsdevelop, but this checkout has onlymain(origin/HEADand the sole local/remote branch). Per the workinginstructions, the work is committed on
main.Secrets Manager; the
SecretsProviderinterface keeps AWS additive. Vaultsupplies secrets after
loadConfig, soDATABASE_URLstill has to arrive byenv or file at boot (Prisma builds its client at import). This is documented.
AGENT_SECRET_KEYis intentionally outside the hotstore: rotating it is an on-chain registration change, so it requires a
restart. Values already copied into SDK objects cannot be zeroed; only the
long-lived store copy is.
migrations. The linter therefore runs on the migration files changed by a PR
or release, which matches “fail a PR that adds a destructive migration”
without blocking every deploy on history.
rather than implementing a calendar-aware grandfather-father-son scheme; the
variables and runbook expose the policy.
RECONCILE_FAKE_RPCreads the existing recordedevent fixture. The reconcile command still uses real RPC when that variable
is absent.
directly instead of adding an IPFS dependency;
pinJsonstill hashes thesame canonical bytes.
the deploy workflow expects
deploy/helm/oracledesk-backendand fails clearlyif it is missing.