test(secrets): group-secret inheritance + masked-read journeys

Two end-to-end journeys via `pic` against a real server:

* `group_secret_is_injected_then_app_value_overrides` — a group-owned
  secret is injected into a descendant app's script through `secrets::get`
  (decrypted under the group AAD), then an app-owned secret of the same
  name shadows it (decrypted under the app AAD). Drives the resolver + both
  owner-AAD open paths against Postgres.
* `group_secret_value_is_masked_from_app_devs` — the §5.3 boundary: an app
  dev (editor on the app, no group role) is denied the secret VALUE (403)
  yet still sees it EXISTS, masked, in `config/effective` (status set,
  owner group, no value); a group_admin reads the value. Proves an app
  runs with config its own devs cannot read.

Also updates the existing app-secrets `ls` journey for the new `env`
column (group secrets are env-scoped).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-06-24 22:09:14 +02:00
parent 30441549d5
commit 11ac168839
4 changed files with 194 additions and 1 deletions

View File

@@ -35,7 +35,7 @@ fn set_ls_rm_round_trip() {
.expect("secrets ls");
let stdout = String::from_utf8(out.stdout).unwrap();
let header = stdout.lines().next().expect("header");
assert_eq!(common::cells(header), vec!["name", "updated_at"]);
assert_eq!(common::cells(header), vec!["name", "env", "updated_at"]);
assert!(
stdout.lines().skip(1).any(|l| l.starts_with("api_key")),
"api_key missing from ls: {stdout}"