Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions netengine/spec/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Spec parsing and models for NetEngine declarative specifications."""

from netengine.spec.models import AuthorityPosture

from netengine.spec.authority import (
Authority,
AuthorityKind,
Expand All @@ -15,6 +17,7 @@
)

__all__ = [
"AuthorityPosture",
"Authority",
"AuthorityKind",
"AuthorityScope",
Expand Down
30 changes: 21 additions & 9 deletions netengine/spec/authority.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,20 +375,32 @@ def world_manifest_from_spec(spec: "NetEngineSpec") -> WorldManifest:

authorities = default_authorities_for_spec(spec)

posture = spec.authority

return WorldManifest(
world_id=spec.metadata.name,
world_name=spec.metadata.name,
lifecycle=spec.metadata.lifecycle,
authority_model="default",
authority_model=posture.authority_model if posture else "default",
authorities=authorities,
dns_root_authority="root-naming",
ca_trust_authority="trust-root",
platform_identity_issuer="platform-identity",
inworld_identity_issuer="inworld-identity",
world_registry_authority="world-root",
domain_registry_authority="domain-registry",
numbering_authority="numbering",
transit_boundary_authority="transit-boundary",
dns_root_authority=(posture.dns_root_authority if posture else None) or "root-naming",
ca_trust_authority=(posture.ca_trust_authority if posture else None) or "trust-root",
platform_identity_issuer=(
(posture.platform_identity_issuer if posture else None) or "platform-identity"
),
inworld_identity_issuer=(
(posture.inworld_identity_issuer if posture else None) or "inworld-identity"
),
world_registry_authority=(
(posture.world_registry_authority if posture else None) or "world-root"
),
domain_registry_authority=(
(posture.domain_registry_authority if posture else None) or "domain-registry"
),
numbering_authority=(posture.numbering_authority if posture else None) or "numbering",
transit_boundary_authority=(
(posture.transit_boundary_authority if posture else None) or "transit-boundary"
),
real_internet_posture=spec.gateway_portal.real_internet.mode,
cross_world_posture=spec.gateway_portal.cross_world.mode,
trust_bundles=_trust_bundles_from_spec(spec),
Expand Down
22 changes: 22 additions & 0 deletions netengine/spec/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,24 @@ class OperatorConfig(SpecModel):
auth: OperatorAuthConfig = Field(default_factory=OperatorAuthConfig)


class AuthorityPosture(SpecModel):
"""Optional top-level authority posture overrides.

This is intentionally not required by MVP specs. Existing examples derive
their authority manifest from established top-level sections via
``default_authorities_for_spec`` and ``world_manifest_from_spec``.
"""

authority_model: str = Field(default="default", description="Authority posture profile")
dns_root_authority: str | None = Field(default=None)
ca_trust_authority: str | None = Field(default=None)
platform_identity_issuer: str | None = Field(default=None)
inworld_identity_issuer: str | None = Field(default=None)
world_registry_authority: str | None = Field(default=None)
domain_registry_authority: str | None = Field(default=None)
numbering_authority: str | None = Field(default=None)
transit_boundary_authority: str | None = Field(default=None)

# ─────────────────────────────────────────────
# ROOT: NETENGINESPEC
# ─────────────────────────────────────────────
Expand All @@ -688,3 +706,7 @@ class NetEngineSpec(SpecModel):
org_apps: OrgAppsPhase = Field(..., description="Phase 9 — org apps")
gateway_portal: GatewayPortal = Field(..., description="Gateway boundary")
operator: OperatorConfig = Field(..., description="Operator API")
authority: AuthorityPosture | None = Field(
default=None,
description="Optional authority posture overrides; omitted specs derive defaults",
)
29 changes: 29 additions & 0 deletions tests/test_authority_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,3 +372,32 @@ def test_world_manifest_from_spec_derives_cross_world_trust_bundles(minimal_spec
assert manifest.trust_bundles[0].mode == GatewayCrossWorldMode.FEDERATED
assert manifest.trust_bundles[0].dns_suffixes == ["world-b.internal"]
assert manifest.trust_bundles[0].peer_root_ca == "-----BEGIN CERTIFICATE-----..."


def test_authority_posture_is_optional_for_existing_examples(minimal_spec) -> None:
from netengine.spec import AuthorityPosture

assert minimal_spec.authority is None
posture = AuthorityPosture(authority_model="custom")
assert posture.authority_model == "custom"


def test_world_manifest_from_spec_applies_optional_authority_posture(minimal_spec) -> None:
from netengine.spec import AuthorityPosture, world_manifest_from_spec

spec = minimal_spec.model_copy(
update={
"authority": AuthorityPosture(
authority_model="custom",
dns_root_authority="custom-root",
ca_trust_authority="custom-trust",
)
}
)

manifest = world_manifest_from_spec(spec)

assert manifest.authority_model == "custom"
assert manifest.dns_root_authority == "custom-root"
assert manifest.ca_trust_authority == "custom-trust"
assert manifest.platform_identity_issuer == "platform-identity"