From e186746e77472d05eaf80a38285e59e67b53a6b7 Mon Sep 17 00:00:00 2001 From: Derek Date: Thu, 8 Oct 2026 12:00:47 +1100 Subject: [PATCH] fix: read the secret marker as x-scalo-secret scalo now marks a secret config field with x-scalo-secret alone, so the contract reader keys on that one name and no longer reads x-dfe-secret. SECRET_MARKERS becomes SECRET_MARKER. The app schema fixtures under tests/fixtures/contract, contract-main and contract-acknowledgements carry the marker under its new name, the name each app emits once it is rebuilt on that scalo. A new test checks every field an app marks reads as a secret, and fails if the fixtures carry a marker the reader does not key on. This must merge together with the 2.2.1 fleet rebuild. An app image built on an older scalo marks secrets only as x-dfe-secret, and this reader would no longer see those marks. --- src/dfe_engine/appmgmt/contract.py | 11 +-- .../dfe-archiver/config-schema.json | 12 +-- .../dfe-fetcher/config-schema.json | 86 +++++++++---------- .../dfe-loader/config-schema.json | 12 +-- .../dfe-receiver/config-schema.json | 6 +- .../dfe-transform-vector/config-schema.json | 2 +- .../dfe-transform-vrl/config-schema.json | 2 +- .../dfe-archiver/config-schema.json | 12 +-- .../dfe-loader/config-schema.json | 12 +-- .../dfe-receiver/config-schema.json | 6 +- .../contract/dfe-archiver/config-schema.json | 12 +-- .../contract/dfe-fetcher/config-schema.json | 60 ++++++------- .../contract/dfe-loader/config-schema.json | 12 +-- .../contract/dfe-receiver/config-schema.json | 8 +- tests/unit/test_appmgmt/test_contract.py | 36 +++++--- .../unit/test_services/test_delivery_keys.py | 4 +- 16 files changed, 151 insertions(+), 142 deletions(-) diff --git a/src/dfe_engine/appmgmt/contract.py b/src/dfe_engine/appmgmt/contract.py index eddebee0f..e1cf729e2 100644 --- a/src/dfe_engine/appmgmt/contract.py +++ b/src/dfe_engine/appmgmt/contract.py @@ -48,11 +48,8 @@ SOURCE_FILE = "source.json" """scalo's own file names - the CLI chooses the directory and nothing else.""" -SECRET_MARKERS = ("x-scalo-secret", "x-dfe-secret") # noqa: S105, RUF100 - schema keywords -"""The schema keywords an app uses to mark a field as credential material. - -scalo writes ``x-scalo-secret``; an app built on an older scalo writes ``x-dfe-secret``. -""" +SECRET_MARKER = "x-scalo-secret" # noqa: S105, RUF100 - a schema keyword +"""The schema keyword scalo writes to mark a field as credential material.""" ENV_NAME = re.compile(r"^[A-Z][A-Z0-9_]*$") """What a key under ``extraEnv`` may be called. @@ -822,8 +819,8 @@ def _wholly_secret(path: str, node: dict, root: dict) -> bool: def _marked_secret(branch: dict) -> bool: - """Whether a schema branch carries either secret marker.""" - return any(branch.get(marker) for marker in SECRET_MARKERS) + """Whether a schema branch carries the secret marker.""" + return bool(branch.get(SECRET_MARKER)) def _masked(value: Any) -> Any: diff --git a/tests/fixtures/contract-acknowledgements/dfe-archiver/config-schema.json b/tests/fixtures/contract-acknowledgements/dfe-archiver/config-schema.json index 7a9736596..f11a45e04 100644 --- a/tests/fixtures/contract-acknowledgements/dfe-archiver/config-schema.json +++ b/tests/fixtures/contract-acknowledgements/dfe-archiver/config-schema.json @@ -209,7 +209,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -446,7 +446,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "bucket": { @@ -477,7 +477,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credentials_path": { @@ -506,7 +506,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "sas_token": { @@ -514,7 +514,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "container": { @@ -548,7 +548,7 @@ }, "secret_key": { "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "bucket": { diff --git a/tests/fixtures/contract-acknowledgements/dfe-fetcher/config-schema.json b/tests/fixtures/contract-acknowledgements/dfe-fetcher/config-schema.json index 434f4ea67..c8dad8c60 100644 --- a/tests/fixtures/contract-acknowledgements/dfe-fetcher/config-schema.json +++ b/tests/fixtures/contract-acknowledgements/dfe-fetcher/config-schema.json @@ -630,7 +630,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -744,7 +744,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "assume_role_arn": { @@ -813,7 +813,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -941,7 +941,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -1024,7 +1024,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -1151,7 +1151,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -1388,7 +1388,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -1491,7 +1491,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -1544,7 +1544,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "use_ssws_header": { @@ -1645,7 +1645,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "use_ssws_header": { @@ -1705,7 +1705,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -1801,7 +1801,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -1847,7 +1847,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -1936,7 +1936,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -1996,7 +1996,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -2092,7 +2092,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -2131,7 +2131,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -2220,7 +2220,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -2273,7 +2273,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -2376,7 +2376,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -2443,7 +2443,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -2566,7 +2566,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -3221,7 +3221,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -3288,7 +3288,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "sas_token": { @@ -3297,7 +3297,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "tenant_id": { @@ -3320,7 +3320,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -3400,7 +3400,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -3531,7 +3531,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -5775,7 +5775,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -5785,7 +5785,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -5803,7 +5803,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -5821,7 +5821,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -5847,7 +5847,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -5869,7 +5869,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -5879,7 +5879,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -5889,7 +5889,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -5907,7 +5907,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -5917,7 +5917,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -5927,7 +5927,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -5944,7 +5944,7 @@ "type": "object", "additionalProperties": { "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "default": {} @@ -6066,7 +6066,7 @@ "connection_string": { "description": "The connection string or URL as a credential spec (`vault:...`, also\nspelled `bao:` or `openbao:`, `env:VAR`, `file:`, or a literal),\nresolved on first use and never logged.", "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": "***REDACTED***" }, @@ -7061,7 +7061,7 @@ "password": { "description": "Password (always redacted in serialisation/debug output).\n\nThe schema default is pinned to the empty string: serialising the real\ndefault outside an expose window yields the mask, and a UI that\npre-filled a password box with `***REDACTED***` would send that as the\npassword.", "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": "" } @@ -7564,7 +7564,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, diff --git a/tests/fixtures/contract-acknowledgements/dfe-loader/config-schema.json b/tests/fixtures/contract-acknowledgements/dfe-loader/config-schema.json index 3e5387a8c..38e638885 100644 --- a/tests/fixtures/contract-acknowledgements/dfe-loader/config-schema.json +++ b/tests/fixtures/contract-acknowledgements/dfe-loader/config-schema.json @@ -465,7 +465,7 @@ }, "password": { "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": "***REDACTED***" }, @@ -491,7 +491,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -533,7 +533,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -543,7 +543,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -683,7 +683,7 @@ }, "password": { "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": "***REDACTED***" }, @@ -947,7 +947,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, diff --git a/tests/fixtures/contract-acknowledgements/dfe-receiver/config-schema.json b/tests/fixtures/contract-acknowledgements/dfe-receiver/config-schema.json index 7a2477148..a639e2654 100644 --- a/tests/fixtures/contract-acknowledgements/dfe-receiver/config-schema.json +++ b/tests/fixtures/contract-acknowledgements/dfe-receiver/config-schema.json @@ -787,7 +787,7 @@ "type": "array", "items": { "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "default": [] @@ -807,7 +807,7 @@ "type": "array", "items": { "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "default": [] @@ -826,7 +826,7 @@ "type": "array", "items": { "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "default": [] diff --git a/tests/fixtures/contract-acknowledgements/dfe-transform-vector/config-schema.json b/tests/fixtures/contract-acknowledgements/dfe-transform-vector/config-schema.json index 6f8c05e12..1cdfe6323 100644 --- a/tests/fixtures/contract-acknowledgements/dfe-transform-vector/config-schema.json +++ b/tests/fixtures/contract-acknowledgements/dfe-transform-vector/config-schema.json @@ -348,7 +348,7 @@ "password": { "description": "SASL password. Leave empty when `secret_dir` supplies it.\n\nTaken literally: Vector does not expand `${VAR}` placeholders, so a\nvalue holding one is refused.", "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": "" }, diff --git a/tests/fixtures/contract-acknowledgements/dfe-transform-vrl/config-schema.json b/tests/fixtures/contract-acknowledgements/dfe-transform-vrl/config-schema.json index 26a6cd38f..493841232 100644 --- a/tests/fixtures/contract-acknowledgements/dfe-transform-vrl/config-schema.json +++ b/tests/fixtures/contract-acknowledgements/dfe-transform-vrl/config-schema.json @@ -257,7 +257,7 @@ }, "password": { "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true } } diff --git a/tests/fixtures/contract-main/dfe-archiver/config-schema.json b/tests/fixtures/contract-main/dfe-archiver/config-schema.json index 2453d3168..7a421f927 100644 --- a/tests/fixtures/contract-main/dfe-archiver/config-schema.json +++ b/tests/fixtures/contract-main/dfe-archiver/config-schema.json @@ -208,7 +208,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -445,7 +445,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "bucket": { @@ -476,7 +476,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credentials_path": { @@ -505,7 +505,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "sas_token": { @@ -513,7 +513,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "container": { @@ -547,7 +547,7 @@ }, "secret_key": { "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "bucket": { diff --git a/tests/fixtures/contract-main/dfe-loader/config-schema.json b/tests/fixtures/contract-main/dfe-loader/config-schema.json index ab85cc2e8..f14b26e93 100644 --- a/tests/fixtures/contract-main/dfe-loader/config-schema.json +++ b/tests/fixtures/contract-main/dfe-loader/config-schema.json @@ -463,7 +463,7 @@ }, "password": { "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": "***REDACTED***" }, @@ -489,7 +489,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -531,7 +531,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -541,7 +541,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -681,7 +681,7 @@ }, "password": { "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": "***REDACTED***" }, @@ -932,7 +932,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, diff --git a/tests/fixtures/contract-main/dfe-receiver/config-schema.json b/tests/fixtures/contract-main/dfe-receiver/config-schema.json index e6da82de5..55b349050 100644 --- a/tests/fixtures/contract-main/dfe-receiver/config-schema.json +++ b/tests/fixtures/contract-main/dfe-receiver/config-schema.json @@ -779,7 +779,7 @@ "type": "array", "items": { "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "default": [] @@ -799,7 +799,7 @@ "type": "array", "items": { "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "default": [] @@ -818,7 +818,7 @@ "type": "array", "items": { "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "default": [] diff --git a/tests/fixtures/contract/dfe-archiver/config-schema.json b/tests/fixtures/contract/dfe-archiver/config-schema.json index f2cb4c3f5..92414aed2 100644 --- a/tests/fixtures/contract/dfe-archiver/config-schema.json +++ b/tests/fixtures/contract/dfe-archiver/config-schema.json @@ -202,7 +202,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -411,7 +411,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "bucket": { @@ -442,7 +442,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credentials_path": { @@ -471,7 +471,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "sas_token": { @@ -479,7 +479,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "container": { @@ -513,7 +513,7 @@ }, "secret_key": { "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "bucket": { diff --git a/tests/fixtures/contract/dfe-fetcher/config-schema.json b/tests/fixtures/contract/dfe-fetcher/config-schema.json index b99c279cd..f1fb70adf 100644 --- a/tests/fixtures/contract/dfe-fetcher/config-schema.json +++ b/tests/fixtures/contract/dfe-fetcher/config-schema.json @@ -569,7 +569,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -683,7 +683,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "assume_role_arn": { @@ -752,7 +752,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -880,7 +880,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -963,7 +963,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -1083,7 +1083,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -1320,7 +1320,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -1423,7 +1423,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -1476,7 +1476,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "use_ssws_header": { @@ -1577,7 +1577,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "use_ssws_header": { @@ -1637,7 +1637,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -1733,7 +1733,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -1779,7 +1779,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -1868,7 +1868,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -1928,7 +1928,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -2024,7 +2024,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -2063,7 +2063,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -2152,7 +2152,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -2205,7 +2205,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -2308,7 +2308,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -2375,7 +2375,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -2478,7 +2478,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -3122,7 +3122,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -3189,7 +3189,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "sas_token": { @@ -3198,7 +3198,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "tenant_id": { @@ -3221,7 +3221,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -3301,7 +3301,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -3432,7 +3432,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "credential_secret": { @@ -3819,7 +3819,7 @@ "password": { "description": "Password (always redacted in serialisation/debug output).\n\nThe schema default is pinned to the empty string: serialising the real\ndefault outside an expose window yields the mask, and a UI that\npre-filled a password box with `***REDACTED***` would send that as the\npassword.", "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": "" } @@ -4302,7 +4302,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, diff --git a/tests/fixtures/contract/dfe-loader/config-schema.json b/tests/fixtures/contract/dfe-loader/config-schema.json index d9cbb044b..359494917 100644 --- a/tests/fixtures/contract/dfe-loader/config-schema.json +++ b/tests/fixtures/contract/dfe-loader/config-schema.json @@ -450,7 +450,7 @@ }, "password": { "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": "***REDACTED***" }, @@ -476,7 +476,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -518,7 +518,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -528,7 +528,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, @@ -643,7 +643,7 @@ }, "password": { "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": "***REDACTED***" }, @@ -907,7 +907,7 @@ "string", "null" ], - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true, "default": null }, diff --git a/tests/fixtures/contract/dfe-receiver/config-schema.json b/tests/fixtures/contract/dfe-receiver/config-schema.json index 592b8f537..d9b4754b3 100644 --- a/tests/fixtures/contract/dfe-receiver/config-schema.json +++ b/tests/fixtures/contract/dfe-receiver/config-schema.json @@ -792,7 +792,7 @@ "type": "array", "items": { "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "default": [] @@ -812,7 +812,7 @@ "type": "array", "items": { "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "default": [] @@ -831,7 +831,7 @@ "type": "array", "items": { "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true }, "default": [] @@ -2288,7 +2288,7 @@ "password": { "description": "Password, redacted wherever it is printed or serialised.", "type": "string", - "x-dfe-secret": true, + "x-scalo-secret": true, "writeOnly": true } }, diff --git a/tests/unit/test_appmgmt/test_contract.py b/tests/unit/test_appmgmt/test_contract.py index d2ac0054a..b32c4c105 100644 --- a/tests/unit/test_appmgmt/test_contract.py +++ b/tests/unit/test_appmgmt/test_contract.py @@ -7,9 +7,10 @@ # Copyright: (c) 2026 HYPERI PTY LIMITED """The reader and resolver, against the contracts the six pinned images emitted. -The fixtures are the real files, byte for byte, so a flattener that stops -descending or starts double counting shows up as a changed leaf total rather than -as a plausible-looking list nobody checks. +The fixtures are the real files, byte for byte but for the secret marker, which +reads ``x-scalo-secret``. So a flattener that stops descending or starts double +counting shows up as a changed leaf total rather than as a plausible-looking list +nobody checks. """ import json @@ -23,7 +24,8 @@ FIXTURES = Path(__file__).parents[2] / "fixtures" / "contract" # Schemas from the builds that hold each source acknowledgement until delivery, -# copied byte for byte from each app's docs/config-schema.json: dfe-receiver +# copied byte for byte from each app's docs/config-schema.json but for the secret +# marker, which reads x-scalo-secret: dfe-receiver # f61c903, dfe-loader edef368, dfe-transform-vrl da42bd2, dfe-archiver 29f201a, # dfe-transform-vector 36dbfa6, dfe-fetcher 0ab0317. HELD = Path(__file__).parents[2] / "fixtures" / "contract-acknowledgements" @@ -77,14 +79,14 @@ def _contract(service: str) -> contract.AppContract: return contract.load_contract(service, FIXTURES) -def _marked_root(root: Path, marker: str = contract.SECRET_MARKERS[0]) -> Path: +def _marked_root(root: Path) -> Path: """A mounted dfe-receiver contract whose one marked field has a name that says nothing.""" schema = { "type": "object", "properties": { "server": { "type": "object", - "properties": {"banner": {"type": "string", marker: True}}, + "properties": {"banner": {"type": "string", contract.SECRET_MARKER: True}}, } }, } @@ -220,6 +222,19 @@ def test_a_marked_secret_is_a_secret_whatever_it_is_called(self): by_path = {f.path: f for f in contract.resolve_config(_contract("dfe-loader"), {}).fields} assert by_path["config.clickhouse.password"].secret is True + @pytest.mark.parametrize("root", [FIXTURES, HELD], ids=["contract", "acknowledgements"]) + def test_every_field_an_app_marks_reads_as_a_secret(self, root): + marked: list[str] = [] + for service in APPS: + found = contract.load_contract(service, root) + by_path = {f.path: f for f in contract.resolve_config(found, {}).fields} + for path, node, _inherited in contract.walk_schema(found.schema): + if path and node.get(contract.SECRET_MARKER) is True: + marked.append(f"{service}:{path}") + assert by_path[f"{contract.CONFIG_ROOT}.{path}"].secret is True, (service, path) + # Fails when the fixtures carry a marker name the reader does not key on. + assert marked + def test_a_list_of_tokens_is_a_secret_before_the_app_marks_it(self): # The shipped receiver marks nothing, and its bearer tokens are a list. by_path = {f.path: f for f in contract.resolve_config(_contract("dfe-receiver"), {}).fields} @@ -318,7 +333,7 @@ def test_a_masked_map_entry_moved_to_another_url_is_refused(self): def test_a_definition_that_lists_itself_is_judged_and_ends(self, marked, secret): node: dict = {"type": "string"} if marked: - node[contract.SECRET_MARKERS[0]] = True + node[contract.SECRET_MARKER] = True schema = { "type": "object", "properties": {"tree": {"type": "array", "items": {"$ref": "#/$defs/Node"}}}, @@ -978,11 +993,8 @@ def test_no_credential_survives_anywhere_in_it(self): ): assert credential not in text - @pytest.mark.parametrize("marker", contract.SECRET_MARKERS) - def test_a_document_naming_its_app_is_read_against_that_app( - self, monkeypatch, tmp_path, marker - ): - monkeypatch.setenv(contract.CONTRACT_DIR_ENV, str(_marked_root(tmp_path, marker))) + def test_a_document_naming_its_app_is_read_against_that_app(self, monkeypatch, tmp_path): + monkeypatch.setenv(contract.CONTRACT_DIR_ENV, str(_marked_root(tmp_path))) contract.reload_contracts() doc = {"deploy": {"service": "dfe-receiver"}, "config": {"server": {"banner": "b-1"}}} # Only the app's marker says the banner is secret. diff --git a/tests/unit/test_services/test_delivery_keys.py b/tests/unit/test_services/test_delivery_keys.py index d44d59b1f..64654ba43 100644 --- a/tests/unit/test_services/test_delivery_keys.py +++ b/tests/unit/test_services/test_delivery_keys.py @@ -10,8 +10,8 @@ The mirrors forbid unknown keys, so a key the app reads and the mirror lacks is refused on the /services path before it reaches anything. The defaults are compared with the schemas the apps emit (``tests/fixtures/contract-acknowledgements``, -copied byte for byte from each app's ``docs/config-schema.json``), not with a -number typed in here. +copied byte for byte from each app's ``docs/config-schema.json`` but for the secret +marker, which reads ``x-scalo-secret``), not with a number typed in here. """ import json