feat(edp): provision Foundry reader grants

This commit is contained in:
Codex
2026-07-19 15:03:48 +03:00
parent 847a08da93
commit def9a24e0d
17 changed files with 891 additions and 7 deletions
@@ -293,6 +293,48 @@ class CanonicalPlatformRegistryTest(unittest.TestCase):
keypair.assert_called_once_with()
private_state.assert_called_once_with()
def test_module_foundry_runtime_prepares_separate_edp_identity_and_grant_roots(self):
with (
mock.patch.object(RUNNER, "ensure_map_gateway_admin_secret") as map_secret,
mock.patch.object(RUNNER, "ensure_foundry_edp_managed_provisioner_keypair") as foundry_keypair,
mock.patch.object(RUNNER, "ensure_root_owned_grant_directory") as grant_directory,
):
RUNNER.prepare_component_runtime("module-foundry", ("server/catalog-server.mjs",))
map_secret.assert_called_once_with()
foundry_keypair.assert_called_once_with()
self.assertEqual(
grant_directory.call_args_list,
[
mock.call(
RUNNER.EXTERNAL_DATA_PLANE_READER_GRANTS_DIR,
"external data plane reader grants",
),
mock.call(
RUNNER.FOUNDRY_BINDING_GRANTS_DIR,
"foundry binding grants",
),
],
)
def test_edp_runtime_prepares_engine_and_foundry_public_trust_independently(self):
entries = ("platform/services/external-data-plane/src/server.mjs",)
with (
mock.patch.object(RUNNER, "ensure_external_data_plane_provisioner_secret") as legacy_secret,
mock.patch.object(RUNNER, "ensure_engine_edp_managed_provisioner_keypair") as engine_keypair,
mock.patch.object(RUNNER, "ensure_foundry_edp_managed_provisioner_keypair") as foundry_keypair,
mock.patch.object(RUNNER, "ensure_root_owned_grant_directory") as grant_directory,
):
RUNNER.prepare_component_runtime("platform", entries)
legacy_secret.assert_called_once_with()
engine_keypair.assert_called_once_with()
foundry_keypair.assert_called_once_with()
grant_directory.assert_called_once_with(
RUNNER.EXTERNAL_DATA_PLANE_READER_GRANTS_DIR,
"external data plane reader grants",
)
def test_partial_publish_path_has_no_publish_runtime_side_effects(self):
entries = ("nodedc-source/server/dataProductPublishGrant/store.js",)
self.assertTrue(RUNNER.touches_engine_data_product_publish_grant(entries))
@@ -441,6 +483,46 @@ class CanonicalPlatformRegistryTest(unittest.TestCase):
(RUNNER.external_data_plane_healthcheck(),),
)
def test_edp_healthcheck_requires_foundry_provisioner_for_the_new_source(self):
with tempfile.TemporaryDirectory(prefix="nodedc-edp-foundry-health-") as directory:
root = Path(directory)
source = root / "platform/services/external-data-plane/src/server.mjs"
source.parent.mkdir(parents=True)
source.write_text(
'foundryReaderBindingProvisioning: config.foundryProvisionerApiEnabled ? "digest+server-resolved-source" : "disabled"\n',
encoding="utf-8",
)
original_root = RUNNER.COMPONENTS["platform"]["payload_root"]
RUNNER.COMPONENTS["platform"]["payload_root"] = root
try:
expected = RUNNER.external_data_plane_healthcheck()["expected_json"]
finally:
RUNNER.COMPONENTS["platform"]["payload_root"] = original_root
self.assertEqual(
expected["foundryReaderBindingProvisioning"],
"digest+server-resolved-source",
)
self.assertEqual(expected["foundryReaderBindingLifetime"], "explicit-revoke")
def test_module_foundry_healthcheck_tracks_candidate_and_rollback_source(self):
with tempfile.TemporaryDirectory(prefix="nodedc-foundry-health-") as directory:
root = Path(directory)
source = root / "server/catalog-server.mjs"
source.parent.mkdir(parents=True)
original_root = RUNNER.COMPONENTS["module-foundry"]["payload_root"]
RUNNER.COMPONENTS["module-foundry"]["payload_root"] = root
try:
source.write_text("const dataProductConsumerProvisioner = true;\n", encoding="utf-8")
candidate = RUNNER.module_foundry_healthcheck()["expected_json"]
source.write_text("const previous = true;\n", encoding="utf-8")
rollback = RUNNER.module_foundry_healthcheck()["expected_json"]
finally:
RUNNER.COMPONENTS["module-foundry"]["payload_root"] = original_root
self.assertEqual(candidate["dataProductConsumerProvisioner"]["configured"], True)
self.assertNotIn("dataProductConsumerProvisioner", rollback)
def test_edp_runtime_never_probes_unselected_platform_services(self):
entries = ("platform/services/external-data-plane/src/server.mjs",)
services = ("external-data-plane",)