Skip to content

Commit d98d662

Browse files
committed
Keep authority posture optional in specs
1 parent ee3ec0b commit d98d662

4 files changed

Lines changed: 75 additions & 9 deletions

File tree

netengine/spec/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""Spec parsing and models for NetEngine declarative specifications."""
22

3+
from netengine.spec.models import AuthorityPosture
4+
35
from netengine.spec.authority import (
46
Authority,
57
AuthorityKind,
@@ -15,6 +17,7 @@
1517
)
1618

1719
__all__ = [
20+
"AuthorityPosture",
1821
"Authority",
1922
"AuthorityKind",
2023
"AuthorityScope",

netengine/spec/authority.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -375,20 +375,32 @@ def world_manifest_from_spec(spec: "NetEngineSpec") -> WorldManifest:
375375

376376
authorities = default_authorities_for_spec(spec)
377377

378+
posture = spec.authority
379+
378380
return WorldManifest(
379381
world_id=spec.metadata.name,
380382
world_name=spec.metadata.name,
381383
lifecycle=spec.metadata.lifecycle,
382-
authority_model="default",
384+
authority_model=posture.authority_model if posture else "default",
383385
authorities=authorities,
384-
dns_root_authority="root-naming",
385-
ca_trust_authority="trust-root",
386-
platform_identity_issuer="platform-identity",
387-
inworld_identity_issuer="inworld-identity",
388-
world_registry_authority="world-root",
389-
domain_registry_authority="domain-registry",
390-
numbering_authority="numbering",
391-
transit_boundary_authority="transit-boundary",
386+
dns_root_authority=(posture.dns_root_authority if posture else None) or "root-naming",
387+
ca_trust_authority=(posture.ca_trust_authority if posture else None) or "trust-root",
388+
platform_identity_issuer=(
389+
(posture.platform_identity_issuer if posture else None) or "platform-identity"
390+
),
391+
inworld_identity_issuer=(
392+
(posture.inworld_identity_issuer if posture else None) or "inworld-identity"
393+
),
394+
world_registry_authority=(
395+
(posture.world_registry_authority if posture else None) or "world-root"
396+
),
397+
domain_registry_authority=(
398+
(posture.domain_registry_authority if posture else None) or "domain-registry"
399+
),
400+
numbering_authority=(posture.numbering_authority if posture else None) or "numbering",
401+
transit_boundary_authority=(
402+
(posture.transit_boundary_authority if posture else None) or "transit-boundary"
403+
),
392404
real_internet_posture=spec.gateway_portal.real_internet.mode,
393405
cross_world_posture=spec.gateway_portal.cross_world.mode,
394406
trust_bundles=_trust_bundles_from_spec(spec),

netengine/spec/models.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,24 @@ class OperatorConfig(SpecModel):
663663
auth: OperatorAuthConfig = Field(default_factory=OperatorAuthConfig)
664664

665665

666+
class AuthorityPosture(SpecModel):
667+
"""Optional top-level authority posture overrides.
668+
669+
This is intentionally not required by MVP specs. Existing examples derive
670+
their authority manifest from established top-level sections via
671+
``default_authorities_for_spec`` and ``world_manifest_from_spec``.
672+
"""
673+
674+
authority_model: str = Field(default="default", description="Authority posture profile")
675+
dns_root_authority: str | None = Field(default=None)
676+
ca_trust_authority: str | None = Field(default=None)
677+
platform_identity_issuer: str | None = Field(default=None)
678+
inworld_identity_issuer: str | None = Field(default=None)
679+
world_registry_authority: str | None = Field(default=None)
680+
domain_registry_authority: str | None = Field(default=None)
681+
numbering_authority: str | None = Field(default=None)
682+
transit_boundary_authority: str | None = Field(default=None)
683+
666684
# ─────────────────────────────────────────────
667685
# ROOT: NETENGINESPEC
668686
# ─────────────────────────────────────────────
@@ -688,3 +706,7 @@ class NetEngineSpec(SpecModel):
688706
org_apps: OrgAppsPhase = Field(..., description="Phase 9 — org apps")
689707
gateway_portal: GatewayPortal = Field(..., description="Gateway boundary")
690708
operator: OperatorConfig = Field(..., description="Operator API")
709+
authority: AuthorityPosture | None = Field(
710+
default=None,
711+
description="Optional authority posture overrides; omitted specs derive defaults",
712+
)

tests/test_authority_spec.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,3 +372,32 @@ def test_world_manifest_from_spec_derives_cross_world_trust_bundles(minimal_spec
372372
assert manifest.trust_bundles[0].mode == GatewayCrossWorldMode.FEDERATED
373373
assert manifest.trust_bundles[0].dns_suffixes == ["world-b.internal"]
374374
assert manifest.trust_bundles[0].peer_root_ca == "-----BEGIN CERTIFICATE-----..."
375+
376+
377+
def test_authority_posture_is_optional_for_existing_examples(minimal_spec) -> None:
378+
from netengine.spec import AuthorityPosture
379+
380+
assert minimal_spec.authority is None
381+
posture = AuthorityPosture(authority_model="custom")
382+
assert posture.authority_model == "custom"
383+
384+
385+
def test_world_manifest_from_spec_applies_optional_authority_posture(minimal_spec) -> None:
386+
from netengine.spec import AuthorityPosture, world_manifest_from_spec
387+
388+
spec = minimal_spec.model_copy(
389+
update={
390+
"authority": AuthorityPosture(
391+
authority_model="custom",
392+
dns_root_authority="custom-root",
393+
ca_trust_authority="custom-trust",
394+
)
395+
}
396+
)
397+
398+
manifest = world_manifest_from_spec(spec)
399+
400+
assert manifest.authority_model == "custom"
401+
assert manifest.dns_root_authority == "custom-root"
402+
assert manifest.ca_trust_authority == "custom-trust"
403+
assert manifest.platform_identity_issuer == "platform-identity"

0 commit comments

Comments
 (0)