Refract Vault: write-only secrets, decrypted only where the job runs
Why the keys for our per-organization secrets had to leave the host environment, and why what replaced them is deliberately small.
FAQ
- Can an Admin view a stored secret in Refract Vault?
No. The vault:write scope, seeded to Admin, can put, replace, delete, and list metadata (name, last four characters, creator, created date). There is no read or reveal field, and a contract test asserts that only write and list fields exist.
- Where does decryption actually happen?
Only in the consumer process, and only for a job the webapp recorded in the same database transaction that enqueued it. The webapp runs with an encrypt capability and is refused before any provider call if it tries to decrypt.
- Why not use HashiCorp Vault, AWS Secrets Manager, Doppler, or Infisical instead?
They're broader, more mature products and the right call for a lot of teams. Our specific problem was a credential in the host environment that could read everything, and a service token for any of them would have lived in that same environment. Refract Vault is a much narrower answer to that one problem.
- Is Refract Vault enabled by default?
No. It's off unless a provider is configured, and a process without it boots without loading the AWS SDK. The local provider is refused at boot outside development and test, and there is no fallback key.
- Does Refract Vault rotate keys automatically?
No. Replacing a secret's value creates a new envelope with a fresh data key on the same secret id. Rotating the KMS key is a recommendation in the docs, and there's no re-wrap tool in the repo yet.
- Does Refract Vault alert on unusual access?
Not by itself. It emits a vault.operation metric and writes audit rows for writes and every use outcome, including refusals, and the docs recommend alerting on top of that. No alert rules ship in the code.
- Is any Refract feature using Vault today?
Not yet. The write and list surface is live behind vault:write, and the job recording and consumer runner are built and tested, but no feature calls them yet. The first intended consumer is a per-organization key for an AI coding tool in Astutely.