Repository navigation
chore(infra): testnet configuration and secrets management - #106
Conversation
…d test USDC asset Adds scripts/fund-testnet-accounts.sh with offline tests (stubbed stellar and curl). Accounts are public keys or Stellar CLI identities; the issuer is a CLI identity, so no key material is read or written. Refs #30
…fine The bundled assets/config.json stays the default; native and flutter run builds can now point at another server through --dart-define(-from-file) without code changes. Refs #30
…mple Testnet defaults are the public values from contracts/deployments/testnet.json; a commented local block shows the env-only switch. The app reads the same file through --dart-define-from-file, so it stays secret-free; Serverpod secrets are documented commented out. Refs #30
…ventory check docs/infra/secrets.md lists every secret (in code or planned per ADR-0003) with purpose, storage, access and rotation. scripts/tests/env-inventory.test.sh checks that .env.example covers every variable read in code, matches testnet.json, and that secrets.md covers every secret. Refs #30
tx new only prints 'Signing transaction: <hash>'; found on the first live testnet run. Refs #30
…rt failure The response file is truncated before each call, and status 000 or an empty body is a failure. Refs #30
…deployed Only the 'already deployed' error (Error(Storage, ExistingValue) / contract already exists, stellar-cli 28.x) is tolerated; any other failure stops before funding and shows the CLI log. Refs #30
…ript with timeouts curl uses --connect-timeout 10 --max-time 60; each stellar call runs under GNU timeout 180 when available and unbounded otherwise. Refs #30
…ACT is blank --dart-define-from-file=../.env defines the key as '' when it is empty. The raw define is now read without a default and resolved by resolveEscrowContractAddress; HirePaymentView takes a nullable address and shows the resolved default. Refs #30
The missing-identity hint now matches the documented command: stellar keys generate <name> --fund --network testnet. Refs #30
docs/infra/secrets.md holds the steps; CONTRIBUTING, README and puls3_server/README link to it. Fixes the stale 'app uses mock data' note, unifies the server start command (dart bin/main.dart --apply-migrations after loading ../.env), the identity generate command and STELLAR_ACCOUNT setup, explains root .env vs puls3_server/.env, the TEST_USDC_AMOUNT unit and a missing separator in contracts/AGENTS.md. Refs #30
|
@moises-cisneros @fercodes @Pericena @XxHugheadxX could you review and approve this one? It sets up the shared testnet config and secrets doc that #31 (deploy) builds on. Quickest path to check it: follow "Run against testnet from a fresh clone" in |
Deploying puls3 with
|
| Latest commit: |
1747c54
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://baae9705.puls3-4lw.pages.dev |
| Branch Preview URL: | https://feat-30-testnet-config.puls3-4lw.pages.dev |
|
@moises-cisneros @fercodes @Pericena @XxHugheadxX friendly reminder: this one still needs a review. It's the base for the Serverpod Cloud deploy (#31), which is ready on a branch and waits on this to merge. CI is green; the quickest check is following "Run against testnet from a fresh clone" in |
moises-cisneros
left a comment
There was a problem hiding this comment.
Approved after checking out the PR and running it.
Ran: the four shell suites (86 / 64 / 144 / 52 passed, 0 failed), flutter analyze (no issues) and flutter test (85 passed). --dart-define-from-file=../.env parses the quoted passphrase line.
Non-blocking:
stellar_explorer_test.dart"the define is unset in tests" fails when runningflutter test --dart-define-from-file=../.env, because.env.examplealready setsPULS3_ESCROW_CONTRACT. CI is unaffected (no defines), but the test could be dropped or made conditional.- The shell tests (including
env-inventory.test.sh) are not in CI, so the "enforced by" claim relies on someone running them. Worth a follow-up issue.
Not run: fund-testnet-accounts.sh against live testnet, gitleaks locally, a full web build.
Closes #30
Summary
Testnet configuration and secrets management for puls3.
.env.examplelists every variable read by the server, the app (dart-defines) and the scripts, each with a comment. Testnet defaults are the public values fromcontracts/deployments/testnet.json. Switching to a local network only changes thePULS3_STELLAR_*values..env, serves the server (set -a; . ../.env; set +a), the app (--dart-define-from-file=../.env) and the scripts. The app gets a newPULS3_API_URLoverride, and a blankPULS3_ESCROW_CONTRACTfalls back to the testnet escrow. Server secrets stay in the git-ignoredpuls3_server/config/passwords.yamllocally and in Serverpod Cloud when deployed.puls3_server/.envholds only the local Docker passwords.docs/infra/secrets.md: a secret | purpose | where stored | who has access | how to rotate table covering every secret in code plus the planned ones (ADR-0003 agent wallets, server signer, LLM key). It also has the canonical "Run against testnet from a fresh clone" path, which CONTRIBUTING and the READMEs link to.scripts/fund-testnet-accounts.sh <public-key|identity>...: Friendbot XLM plus the scripted test USDC asset (PUSDC) from spike: agent payment rail and wallet custody on Stellar #7, with timeouts and strict error handling. Circle USDC is faucet-only and cannot be scripted.scripts/tests/env-inventory.test.shkeeps code,.env.example,secrets.mdandtestnet.jsonin sync.Acceptance criteria
cp .env.example .env(testnet values prefilled) plusscripts/setup-local-secrets.shis enough to run the server and the app against testnet. See "Run against testnet from a fresh clone" indocs/infra/secrets.md..gitignorecovers.env,passwords.yamland key files (output below).secrets.md(enforced byscripts/tests/env-inventory.test.sh).localtotestnetneeds only env changes, no code changes: the server readsPULS3_STELLAR_*, the app readsPULS3_API_URL/PULS3_ESCROW_CONTRACT.Verification evidence
Live funding run on testnet (
scripts/fund-testnet-accounts.shwith a throwaway identity):GCJOMHOLKJJUMFCBC56ZIZTINBAFARFQIWNM4MA4GJ6RJZQI4KH3RIB3PUSDC:GDJUWQHLXXSKF6AFLMWFZT37WRRIL4VRGW5P7SB3QPW2F4MWPNYCPHEU(SACCCD5CN7HFEZMSSNL7JCRAMR53ANY2UQYBSCJ744QG3IQIRRT6HWIFFHO)f9c5e949540dd34981358c5eb3d1223233c14da5e7e7a5dcebf0cdc9909f83d45acc971ef2f8afb7114905a23eb5f799fd61b237a66f494b996020db226933a3ceb062f6a5273c0aa76ac211bc6750ca5a660147ea6277e90725338c4f7114344b8a653a375d3f3dc5ff424000b7d3fca25573cdcf23c45df1f1142aad5abaf8Notes for reviewers
PUSDCis not on the escrow allow-list (Circle USDC only). It is for funding and direct payments. Escrow jobs on testnet still need Circle USDC from the faucet.defaultEscrowContractAddressis no longerconst(a const can't trim a blank define), soHirePaymentViewnow takes a nullableescrowContractAddressand shows the testnet default when it is null..env: the app reads it with--dart-define-from-file. Today onlyPULS3_API_URLandPULS3_ESCROW_CONTRACTare compiled into the app, and both are public.Follow-ups
scripts/tests/are not run in CI.env-inventory.test.shonly finds'PULS3_*'Dart literals and${NAME:-...}shell reads. Other read styles are missed, and a commented-out line in.env.examplecounts as "listed".Signing transaction: <hash>) and the "SAC already exists" match were checked against stellar-cli 28.1, while CI pins 28.0. Re-check the output format when either version moves.TEST_USDC_AMOUNT.puls3-test-usdc-issueridentity still exists locally but its account is gone. The script does not recover yet; for now, runstellar keys rm puls3-test-usdc-issuerand run it again.PULS3_API_URLat Pages build time (--dart-define=PULS3_API_URL=<server>). The Pages build is not served by the server, so it will not getconfig.jsonfrom it.