feat(foundry): support restricted subject aspects

This commit is contained in:
Codex
2026-07-24 09:31:34 +03:00
parent 03aa9e3e7e
commit 49f0c449c1
13 changed files with 313 additions and 15 deletions
+38
View File
@@ -80,6 +80,7 @@ for (const policy of consumerPolicies) {
"terminalStatuses",
"statusContract",
"consumerContract",
"dataClass",
"removeMode",
]);
requireValue(Object.keys(policy).every((key) => allowedPolicyKeys.has(key)), `unsupported data product consumer policy key: ${policy.id ?? "unknown"}`);
@@ -89,6 +90,7 @@ for (const policy of consumerPolicies) {
requireValue(typeof policy.productVersion === "string" && /^\d+\.\d+\.\d+$/.test(policy.productVersion), `invalid data product consumer product version: ${policy.id ?? "unknown"}`);
requireValue(Array.isArray(policy.terminalStatuses) && policy.terminalStatuses.every((value) => typeof value === "string" && /^[a-z0-9_-]{1,64}$/.test(value)), `invalid terminal statuses: ${policy.id ?? "unknown"}`);
requireValue(policy.removeMode === "canonical-tombstone-or-snapshot-rebase", `invalid remove mode: ${policy.id ?? "unknown"}`);
requireValue(["operational", "restricted"].includes(policy.dataClass ?? "operational"), `invalid data class: ${policy.id ?? "unknown"}`);
requireValue(["none", "observed-at"].includes(freshness), `invalid freshness mode: ${policy.id ?? "unknown"}`);
if (policy.consumerContract !== undefined) {
const contract = policy.consumerContract;
@@ -205,6 +207,42 @@ requireValue(JSON.stringify(unitProfileV1Policy?.consumerContract?.fieldProjecti
requireValue(JSON.stringify(unitProfileV1Policy?.consumerContract?.geometryTypes) === JSON.stringify([]), "fleet.units.profile.current.v1 must remain a non-geometric aspect");
requireValue(!/(provider|tenant|endpoint|credential|token|secret|authorization)/i.test(JSON.stringify(unitProfileV1Policy)), "fleet.units.profile.current.v1 consumer policy crosses the transport/secret boundary");
const unitContactsV1Policy = consumerPolicies.find(
(policy) => policy.dataProductId === "fleet.units.contacts.current.v1"
&& policy.productVersion === "1.0.0",
);
const unitContactsV1Projection = [
"device_imei",
"device_phone_primary",
"device_phone_secondary",
"display_name",
"provider_creator_login",
];
requireValue(
unitContactsV1Policy?.id === "map-moving-object-unit-contacts-current-v1"
&& unitContactsV1Policy?.version === "1.0.0",
"fleet.units.contacts.current.v1 consumer policy is missing",
);
requireValue(
unitContactsV1Policy?.dataClass === "restricted",
"fleet.units.contacts.current.v1 must be explicitly restricted",
);
requireValue(
JSON.stringify(unitContactsV1Policy?.consumerContract?.fieldProjection)
=== JSON.stringify(unitContactsV1Projection),
"fleet.units.contacts.current.v1 field projection must be exact",
);
requireValue(
JSON.stringify(unitContactsV1Policy?.consumerContract?.geometryTypes) === JSON.stringify([]),
"fleet.units.contacts.current.v1 must remain a non-geometric aspect",
);
requireValue(
!/(tenant|endpoint|credential|token|secret|authorization)/i.test(
JSON.stringify(unitContactsV1Policy),
),
"fleet.units.contacts.current.v1 consumer policy crosses the transport/secret boundary",
);
const ids = components.components.map((component) => component.id);
requireValue(new Set(ids).size === ids.length, "component ids must be unique");
const candidateIds = candidates.candidates.map((component) => component.id);