Sealed Install Enforcement Contract

Currency check 2026-10-07: owner paths/source placement verified against 3238bd511a37e199ae99d4f17be2f13eabec8dd7. The supported boundary is Platform posture custody and OfflineKit carrier custody (src/Platform/StellaOps.Platform.WebService/Endpoints/EnvironmentStateEndpoints.cs). Re-verify the host mount and owning endpoint extension together. This is source verification; deployment and broader audit coverage are separate evidence. Other dated findings retain their stated dates. Re-verify: rg -n "MapGroup|Map.*Endpoints|AddHostedService" src/Platform/StellaOps.Platform.WebService/Endpoints/EnvironmentStateEndpoints.cs, then inspect the endpoint extension or library pointer cited at the operation.

Supported implementation

The proposed TaskRunner sealed_install flag and pre-execution enforcer were never shipped as written. The retained design is unsupported. Current posture, egress and import behavior below does not implement that pack flag.

Posture is held by Platform, exchange custody by OfflineKit, and imported content by the service that owns the domain. The Controller/Time predecessor hosts, their HTTP DTOs and their telemetry meters are withdrawn source. There is no replacement standalone time service to deploy.

ConcernSupported surface and owner
Posture custodyPlatform GET/PUT /api/v1/platform/environment-state/{stateClass}/{scope}; classes airgap-seal and time-anchor, default CLI scope installation
Seal/unseal/statusstella airgap seal, stella airgap unseal, stella airgap status declare/read Platform state with no local marker fallback
Verified time declarationstella airgap time-anchor declare --token anchor.tsr --trust-roots tsa-chain.pem; verification precedes declaration
Time readbackstella airgap time-anchor status --trust-roots tsa-chain.pem re-verifies the stored proof against supplied roots
Carrier import/validationOfflineKit POST /api/offlinekit/v1/import, POST /api/offlinekit/v1/validate
Custody and part stateOfflineKit GET /api/offlinekit/v1/status, GET /api/offlinekit/v1/manifest
Re-offer a failed/superseded partPOST /api/offlinekit/v1/imports/{importId}/parts/{domain}/activate; activated is terminal

Platform stores opaque JSON and enforces class custody, not air-gap semantics. Its read policy accepts envstate:read or the air-gap status grant; declaring airgap-seal needs envstate:airgap-seal:write (the recorded airgap:seal grant is accepted by that custody policy), and time-anchor needs envstate:time-anchor:write. OfflineKit import/validate use airgap:import; custody status/manifest use airgap:status:read. Check the current Authority and Platform policy registrations before assigning grants.

AirGapSealInterpreter and AirGapTimeAnchorInterpreter in src/__Libraries/StellaOps.AirGap.Policy/StellaOps.AirGap.Policy/Posture/ distinguish Declared, NotDeclared and Unreadable. Missing/unreadable state is not a measured sealed/unsealed result; an absent anchor is not fresh. Consumers read their environment-state replica so a Platform outage does not force a cross-service posture read.

RFC3161 verification is the library under src/OfflineKit/__Libraries/StellaOps.AirGap.Time.Verification/. The CLI writer checks the token signature and supplied trust chain without certificate downloads or revocation checking, and records revocationChecked: false. Roughtime remains an enum member but has no current verifier. Consumers re-verify stored proof with the public trust purpose timestamp-authority; a declared timestamp alone is not verification evidence.

For sealed import, OfflineKitImportPostureGate refuses a missing, unreadable or breached trusted time anchor with 409. Warning age admits with a warning. Unsealed/undeclared posture admits; an unreadable posture replica admits with a warning, as implemented. A verified carrier means custody, not activation: each part is offered to its registered owner. Unsupported parts report PART_ACTIVATOR_NOT_REGISTERED; owner activation can fail while custody remains verified.

AirGap:Egress and the in-process IEgressPolicy interpreter govern outbound calls. Sealing state is a declaration, not firewall proof. Apply and verify network controls using the Compose/host tooling in the current sealing guide. Egress policy is a sealed-mode gate, not an SSRF control.

Source pointers:

Operator references

Historical TaskRunner sealed-install design and 2026-05-30 reconciliation (superseded 2026-09-14)

The remainder records the predecessor implementation or unlanded design at the dates stated in its text. All routes, host names, source paths, DTOs, metrics and examples in this section are historical comparison, including sentences that originally said “current” or “today”. They are not instructions for the consolidated estate. The supported section and owner source above supersede them. Do not rebuild or deploy a predecessor from these examples.

Status: SUPERSEDED — NOT IMPLEMENTED AS WRITTEN Version: 1.0.0 (historical) Last Updated: 2025-12-06 (last reconciled against source 2026-05-30) Owner: AirGap Controller Guild Originally Unblocked: TASKRUN-AIRGAP-57-001, TASKRUN-AIRGAP-58-001 (both in the now-deleted TaskRunner service)

[!WARNING] Reconciliation note (2026-05-30). This contract was authored against a TaskRunner service that has since been deleted from the monorepo. There is no src/TaskRunner/directory, and StellaOps.Auth.Abstractions/StellaOpsScopes.cs (lines 755-758) records that the taskrunner:* scopes were “REMOVED (service deleted, constants kept for DB/migration backward compat).” The archived sprint docs-archive/implplan/SPRINT_0157_0001_0001_taskrunner_i.md shows tasks TASKRUN-AIRGAP-57-001/58-001 were marked DONE inside src/TaskRunner/StellaOps.TaskRunner, but that code no longer ships.

Concretely, none of the following exist anywhere in src/: a sealed_install pack-manifest flag, a SealedInstallEnforcer class, a SealedRequirements/SealedInstallViolation type, or the error codes / exit codes / env vars described below. The pseudo-code, JSON schemas, decision matrices, and CLI flows in this document are aspirational / historical and do not reflect shipped behaviour.

What does ship today (see §8):

  • AirGap Controller — GET/POST /system/airgap/{status,seal,unseal,verify} (src/AirGap/StellaOps.AirGap.Controller), gated on the three catalogued scopes airgap:status:read / airgap:seal / airgap:import (/verify shares airgap:status:read).
  • Policy Engine sealed-mode — SealedModeService (src/Policy/StellaOps.Policy.Engine/AirGap/, contract CONTRACT-SEALED-MODE-004), the real fail-closed enforcement gated on IEgressPolicy.IsSealed.
  • stella airgap CLI — import, seal, unseal, status, time-anchor, export-evidence subcommands (registered in src/Cli/StellaOps.Cli/Commands/CommandFactory.cs; AirGapCommandGroup.cs is a non-wired legacy group nothing constructs from the command line). (Currency update 2026-09-02, SPRINT_20260722_025 OK-5: seal/unseal now exist and declare posture in Platform’s environment-state custodian — the sentence previously here recording their absence is superseded. There is still no stella pack … group at all — deleted 2026-09-14, SPRINT_20260914_003 JEF-4.)

The remainder of this document (§§1-7) is retained for historical context. Treat it as a DRAFT design that was never landed in its specified form; consult §8 for the implemented surface. For the authoritative, reconciled sealed-mode contract, see Sealed Mode (CONTRACT-SEALED-MODE-004).

Overview

This contract was intended to define sealed-install enforcement semantics for StellaOps air-gapped deployments: when a pack or task declared sealed_install: true, a Task Runner would refuse to execute if the environment was not properly sealed.

[!NOTE] NOT IMPLEMENTED. No sealed_install flag is honoured by any shipping service. The Task Runner that would have enforced it has been removed. See §8 for the sealed-mode enforcement that actually ships (Policy Engine SealedModeService + AirGap Controller egress policy).

Architecture

┌─────────────────────────────────────────────────────────────────────────────┐
│                     Sealed Install Enforcement Flow                          │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  ┌──────────────┐     ┌──────────────┐     ┌──────────────┐                 │
│  │  Task Pack   │     │ Task Runner  │     │   AirGap     │                 │
│  │              │────>│              │────>│  Controller  │                 │
│  │ sealed_      │     │ Enforcement  │     │              │                 │
│  │ install:true │     │ Check        │     │ /status      │                 │
│  └──────────────┘     └──────────────┘     └──────────────┘                 │
│                              │                    │                          │
│                              ▼                    ▼                          │
│                       ┌──────────────────────────────────┐                  │
│                       │         Decision Matrix           │                  │
│                       │                                   │                  │
│                       │  Pack: sealed    Env: sealed      │                  │
│                       │  ──────────────  ────────────     │                  │
│                       │  true            true     → RUN   │                  │
│                       │  true            false    → DENY  │                  │
│                       │  false           true     → RUN   │                  │
│                       │  false           false    → RUN   │                  │
│                       └──────────────────────────────────┘                  │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

1. Pack Declaration (DRAFT — not implemented)

[!WARNING] The sealed_install manifest flag and sealed_requirements block below do not exist in any shipping pack manifest schema. A repo-wide search for sealed_install / SealedInstall in src/ returns no matches. This section is a never-landed design.

1.1 Sealed Install Flag

Packs declare their sealed requirement in the pack manifest:

{
  "pack_id": "compliance-scan-airgap",
  "version": "1.0.0",
  "name": "Air-Gap Compliance Scanner",
  "sealed_install": true,
  "sealed_requirements": {
    "min_bundle_version": "2025.10.0",
    "max_advisory_staleness_hours": 168,
    "require_time_anchor": true,
    "allowed_offline_duration_hours": 720
  }
}

1.2 Sealed Requirements Schema

{
  "type": "object",
  "properties": {
    "sealed_install": {
      "type": "boolean",
      "default": false,
      "description": "If true, pack MUST run in sealed environment"
    },
    "sealed_requirements": {
      "type": "object",
      "properties": {
        "min_bundle_version": {
          "type": "string",
          "description": "Minimum air-gap bundle version"
        },
        "max_advisory_staleness_hours": {
          "type": "integer",
          "minimum": 1,
          "default": 168,
          "description": "Maximum age of advisory data in hours"
        },
        "require_time_anchor": {
          "type": "boolean",
          "default": true,
          "description": "Require valid time anchor"
        },
        "allowed_offline_duration_hours": {
          "type": "integer",
          "minimum": 1,
          "default": 720,
          "description": "Maximum allowed offline duration"
        },
        "require_signature_verification": {
          "type": "boolean",
          "default": true,
          "description": "Require bundle signature verification"
        }
      }
    }
  }
}

2. Environment Detection (DRAFT — see §8 for the real API)

2.1 Sealed Mode Status API

[!WARNING] INCORRECT — the path, scope, and response shape below do not match the implementation. The real endpoint is GET /system/airgap/status (not /api/v1/airgap/status), it requires the airgap:status:read scope, and it returns AirGapStatusResponse — see §8.1 for the actual contract. None of the fields mode, sealed_at, sealed_by, bundle_version, bundle_digest, last_advisory_update, advisory_staleness_hours, egress_blocked, or network_policy exist in the shipping response. Air-gap staleness is expressed in seconds against a StalenessBudget (Warning/Breach), not in “advisory staleness hours”, and is tracked per content kind via ContentStaleness.

The original (unimplemented) design had the Task Runner query the AirGap Controller as follows:

GET /api/v1/airgap/status     # NOT IMPLEMENTED — real path is GET /system/airgap/status

Response (speculative shape — does not match AirGapStatusResponse):

{
  "sealed": true,
  "mode": "sealed",
  "sealed_at": "2025-12-01T00:00:00Z",
  "sealed_by": "ops-admin@company.com",
  "bundle_version": "2025.10.0",
  "bundle_digest": "sha256:abc123...",
  "last_advisory_update": "2025-12-01T00:00:00Z",
  "advisory_staleness_hours": 120,
  "time_anchor": {
    "timestamp": "2025-12-01T00:00:00Z",
    "signature": "base64...",
    "valid": true,
    "expires_at": "2025-12-31T00:00:00Z"
  },
  "egress_blocked": true,
  "network_policy": "deny-all"
}

2.2 Detection Heuristics

[!WARNING] NOT IMPLEMENTED. There is no heuristic sealed-mode detector. Sealed state is determined deterministically: the AirGap Controller persists explicit seal/unseal state per tenant (AirGapState.Sealed), and the Policy Engine reads IEgressPolicy.IsSealed (true iff EgressPolicyMode.Sealed). There is no DNS/port-probing fallback, no AIRGAP_MODE env var consumed by this path, no /etc/stellaops/sealed sentinel file, and no “0.7 heuristic score” anywhere in src/.

The original design proposed the following fallback heuristics (none of which ship):

HeuristicWeightIndicates
No external DNS resolutionHighSealed
Blocked ports 80, 443HighSealed
AIRGAP_MODE=sealed env varHighSealed
/etc/stellaops/sealed file existsMediumSealed
No internet connectivityMediumSealed
Local-only registry configuredLowSealed

Combined heuristic score threshold: 0.7 to consider environment sealed.

3. Enforcement Logic (DRAFT — illustrative pseudo-code only)

[!WARNING] NOT IMPLEMENTED. The SealedInstallEnforcer, EnforcementResult, SealedRequirements, SealedInstallViolation, and RequirementViolation types below do not exist in src/. No service performs a min_bundle_version / max_advisory_staleness_hours / require_time_anchor pre-execution check against a pack flag. The closest shipping enforcement is SealedModeService.EnforceBundleImportAsync (src/Policy/StellaOps.Policy.Engine/AirGap/SealedModeService.cs), which gates bundle import (not pack execution) on IEgressPolicy.IsSealed and time-anchor staleness, returning SealedModeEnforcementResult(Allowed, Reason, Remediation). The pseudo-code below is retained only to convey the original intent.

3.1 Pre-Execution Check

// ILLUSTRATIVE / NOT IMPLEMENTED — no such type exists in src/
public sealed class SealedInstallEnforcer
{
    public async Task<EnforcementResult> EnforceAsync(
        TaskPack pack,
        CancellationToken ct = default)
    {
        // If pack doesn't require sealed install, allow
        if (!pack.SealedInstall)
        {
            return EnforcementResult.Allowed("Pack does not require sealed install");
        }

        // Get environment sealed status
        var status = await _airgapController.GetStatusAsync(ct);

        // Core check: environment must be sealed
        if (!status.Sealed)
        {
            return EnforcementResult.Denied(
                "SEALED_INSTALL_VIOLATION",
                "Pack requires sealed environment but environment is not sealed",
                new SealedInstallViolation
                {
                    PackId = pack.PackId,
                    RequiredSealed = true,
                    ActualSealed = false,
                    Recommendation = "Activate sealed mode with: stella airgap seal"
                });
        }

        // Check sealed requirements
        if (pack.SealedRequirements != null)
        {
            var violations = ValidateRequirements(pack.SealedRequirements, status);
            if (violations.Any())
            {
                return EnforcementResult.Denied(
                    "SEALED_REQUIREMENTS_VIOLATION",
                    "Sealed requirements not met",
                    violations);
            }
        }

        return EnforcementResult.Allowed("Sealed install requirements satisfied");
    }

    private List<RequirementViolation> ValidateRequirements(
        SealedRequirements requirements,
        SealedModeStatus status)
    {
        var violations = new List<RequirementViolation>();

        // Bundle version check
        if (requirements.MinBundleVersion != null)
        {
            if (Version.Parse(status.BundleVersion) < Version.Parse(requirements.MinBundleVersion))
            {
                violations.Add(new RequirementViolation
                {
                    Requirement = "min_bundle_version",
                    Expected = requirements.MinBundleVersion,
                    Actual = status.BundleVersion,
                    Message = $"Bundle version {status.BundleVersion} < required {requirements.MinBundleVersion}"
                });
            }
        }

        // Advisory staleness check
        if (status.AdvisoryStalenessHours > requirements.MaxAdvisoryStalenessHours)
        {
            violations.Add(new RequirementViolation
            {
                Requirement = "max_advisory_staleness_hours",
                Expected = requirements.MaxAdvisoryStalenessHours.ToString(),
                Actual = status.AdvisoryStalenessHours.ToString(),
                Message = $"Advisory data is {status.AdvisoryStalenessHours}h old, max allowed is {requirements.MaxAdvisoryStalenessHours}h"
            });
        }

        // Time anchor check
        if (requirements.RequireTimeAnchor && (status.TimeAnchor == null || !status.TimeAnchor.Valid))
        {
            violations.Add(new RequirementViolation
            {
                Requirement = "require_time_anchor",
                Expected = "valid time anchor",
                Actual = status.TimeAnchor?.Valid.ToString() ?? "missing",
                Message = "Valid time anchor required but not present"
            });
        }

        return violations;
    }
}

3.2 Decision Matrix

Pack sealed_installEnvironment SealedBundle ValidAdvisories FreshResult
truetruetruetrue✅ RUN
truetruetruefalse⚠️ WARN + RUN (if within grace)
truetruefalse*❌ DENY
truefalse**❌ DENY
falsetrue**✅ RUN
falsefalse**✅ RUN

3.3 Grace Period Handling

For advisory staleness, a grace period can be configured:

# etc/taskrunner.yaml
enforcement:
  sealed_install:
    staleness_grace_period_hours: 24
    staleness_warning_threshold_hours: 120
    deny_on_staleness: true  # or false for warn-only

4. Refusal Semantics (DRAFT — codes below do not exist)

[!WARNING] NOT IMPLEMENTED. The error code SEALED_INSTALL_VIOLATION (and SEALED_REQUIREMENTS_VIOLATION, BUNDLE_VERSION_VIOLATION, ADVISORY_STALENESS_VIOLATION, TIME_ANCHOR_VIOLATION, SIGNATURE_VERIFICATION_VIOLATION) and the CLI exit codes 40-44 below appear nowhere in src/. The shipping sealed-mode error codes are the SealedModeErrorCodes.* constants used by SealedModeService (e.g. staleness-breach / staleness-warning); the AirGap Controller verify endpoint returns a VerifyResponse(Valid, Reason) rather than a coded error envelope.

4.1 Error Response

When enforcement denies execution (speculative shape — not emitted by any service):

{
  "error": {
    "code": "SEALED_INSTALL_VIOLATION",
    "message": "Pack requires sealed environment but environment is not sealed",
    "details": {
      "pack_id": "compliance-scan-airgap",
      "pack_version": "1.0.0",
      "sealed_install_required": true,
      "environment_sealed": false,
      "violations": [],
      "recommendation": "Activate sealed mode with: stella airgap seal"
    }
  },
  "status": "rejected",
  "rejected_at": "2025-12-06T10:00:00Z"
}

4.2 CLI Exit Codes

CodeNameDescription
40SEALED_INSTALL_VIOLATIONPack requires sealed but environment is not
41BUNDLE_VERSION_VIOLATIONBundle version below minimum
42ADVISORY_STALENESS_VIOLATIONAdvisory data too stale
43TIME_ANCHOR_VIOLATIONTime anchor missing or invalid
44SIGNATURE_VERIFICATION_VIOLATIONBundle signature verification failed

4.3 Audit Logging

All enforcement decisions are logged:

{
  "event_type": "sealed_install_enforcement",
  "timestamp": "2025-12-06T10:00:00Z",
  "pack_id": "compliance-scan-airgap",
  "pack_version": "1.0.0",
  "decision": "denied",
  "reason": "SEALED_INSTALL_VIOLATION",
  "environment": {
    "sealed": false,
    "bundle_version": null,
    "advisory_staleness_hours": null
  },
  "user": "task-runner-service",
  "tenant_id": "550e8400-e29b-41d4-a716-446655440000"
}

5. Integration Points (DRAFT — TaskRunner deleted)

[!WARNING] NOT IMPLEMENTED. The src/TaskRunner/ service that hosted this integration has been removed from the monorepo, so the execution-pipeline hook below has no host. The CLI commands shown (stella pack run …, “Activate sealed mode: stella airgap seal”) do not exist — the real stella airgap group exposes only export, import, diff, status, and jobs (src/Cli/StellaOps.Cli/Commands/AirGapCommandGroup.cs); seal/unseal are HTTP-only operations on the AirGap Controller.

5.1 Task Runner Integration

// NOT IMPLEMENTED — TaskRunner service removed; no such pipeline exists
// In TaskRunner execution pipeline
public async Task<TaskResult> ExecuteAsync(TaskPack pack, TaskContext context)
{
    // Pre-execution enforcement
    var enforcement = await _sealedInstallEnforcer.EnforceAsync(pack);
    if (!enforcement.Allowed)
    {
        await _auditLogger.LogEnforcementDenialAsync(pack, enforcement);
        return TaskResult.Rejected(enforcement);
    }

    // Continue with execution
    return await _executor.ExecuteAsync(pack, context);
}

5.2 CLI Integration

# Check sealed status before running pack
$ stella pack run …   # NEVER SHIPPED: the Task Pack verb group was deleted 2026-09-14 (SPRINT_20260914_003 JEF-4)

Error: Sealed install violation
  Pack 'compliance-scan-airgap' requires a sealed environment.

  Current environment:
    Sealed: false

  To resolve:
    1. Import an air-gap bundle: stella airgap import <bundle.tar.gz>
    2. Activate sealed mode: stella airgap seal
    3. Verify status: stella airgap status

  Exit code: 40

6. Configuration (DRAFT — keys/vars below not honoured)

[!WARNING] NOT IMPLEMENTED. The etc/taskrunner.yaml enforcement.sealed_install.* keys and the env vars AIRGAP_MODE, AIRGAP_CONTROLLER_URL, and SEALED_INSTALL_BYPASS are not consumed by any shipping service (no SEALED_INSTALL_BYPASS or sealed-install enforcement config reader exists in src/). Real sealed-mode behaviour is configured through the egress policy (EgressPolicy.Options, EgressPolicyMode) and the AirGap Controller startup options (AirGapStartupOptions); staleness is configured via StalenessBudget (Warning/Breach seconds) on the seal request, not via hour-based grace periods.

6.1 Task Runner Configuration

# etc/taskrunner.yaml
enforcement:
  sealed_install:
    enabled: true

    # Staleness handling
    staleness_grace_period_hours: 24
    staleness_warning_threshold_hours: 120
    deny_on_staleness: true

    # Fallback detection
    use_heuristic_detection: true
    heuristic_threshold: 0.7

    # Logging
    log_all_decisions: true
    audit_retention_days: 365

6.2 Environment Variables

VariableDescriptionDefault
AIRGAP_MODEForce sealed mode detection—
AIRGAP_CONTROLLER_URLAirGap controller endpointhttp://localhost:8080
SEALED_INSTALL_BYPASSBypass enforcement (dev only)false

7. Tasks Unblocked (historical — service since deleted)

This contract originally unblocked the tasks below. They were marked DONE inside the src/TaskRunner/StellaOps.TaskRunner service (see docs-archive/implplan/SPRINT_0157_0001_0001_taskrunner_i.md), which has since been removed from the monorepo. The delivered code therefore no longer ships.

Task IDDescriptionStatus
TASKRUN-AIRGAP-57-001Sealed install enforcement❌ Removed with TaskRunner service
TASKRUN-AIRGAP-58-001Sealed install CLI integration❌ Removed with TaskRunner service

8. Actual Implementation (as of 2026-05-30)

This section documents the sealed-mode enforcement that actually ships, replacing the aspirational §§1-7 above.

8.1 AirGap Controller HTTP API

Source: src/AirGap/StellaOps.AirGap.Controller/Endpoints/AirGapEndpoints.cs. All routes are under the /system/airgap group and resolve the tenant from the stellaops:tenant/tid claim or x-tenant-id header.

Method & PathScope (policy)Handler / Contract
GET /system/airgap/statusairgap:status:read (AirGapPolicies.StatusRead)Returns AirGapStatusResponse
POST /system/airgap/sealairgap:seal (AirGapPolicies.Seal)Body SealRequest; returns AirGapStatusResponse
POST /system/airgap/unsealairgap:seal (AirGapPolicies.Seal)Returns AirGapStatusResponse
POST /system/airgap/verifyairgap:status:read (AirGapPolicies.Verify)Body VerifyRequest; returns VerifyResponse(Valid, Reason)

Canonical scope constants live in StellaOps.Auth.Abstractions/StellaOpsScopes.cs: AirgapStatusRead = "airgap:status:read", AirgapSeal = "airgap:seal", AirgapImport = "airgap:import". There is no airgap:verify scope: the AirGapPolicies.Verify policy asserts AirgapStatusRead (Program.cs:59-69), because verification is a read-only integrity check.

AirGapStatusResponse(Endpoints/Contracts/AirGapStatusResponse.cs):

{
  "tenantId": "default",
  "sealed": true,
  "policyHash": "sha256:…",
  "timeAnchor": {
    "anchorTime": "2025-12-01T00:00:00Z",
    "source": "roughtime",
    "format": "…",
    "signatureFingerprint": "…",
    "tokenDigest": "…"
  },
  "staleness": {
    "ageSeconds": 432000,
    "warningSeconds": 3600,
    "breachSeconds": 7200,
    "isWarning": false,
    "isBreach": true
  },
  "driftSeconds": 432000,
  "driftBaselineSeconds": 0,
  "secondsRemaining": 0,
  "contentStaleness": {
    "advisories": { "ageSeconds": 0, "secondsRemaining": 7200, "isWarning": false, "isBreach": false }
  },
  "lastTransitionAt": "2025-12-01T00:00:00Z",
  "evaluatedAt": "2025-12-06T10:00:00Z"
}

SealRequest(Endpoints/Contracts/SealRequest.cs) carries a required policyHash, an optional timeAnchor (StellaOps.AirGap.Time.Models.TimeAnchor), an optional stalenessBudget (StalenessBudget(WarningSeconds, BreachSeconds), default 3600/7200), and an optional per-content contentBudgets map.

8.2 Policy Engine sealed-mode (CONTRACT-SEALED-MODE-004)

Source: src/Policy/StellaOps.Policy.Engine/AirGap/ (SealedModeService, SealedModeModels, ISealedModeService). This is the real fail-closed enforcement primitive:

8.3 CLI surface

Source: src/Cli/StellaOps.Cli/Commands/AirGapCommandGroup.cs. The stella airgap group exposes:

CommandPurpose
stella airgap exportExport a sealed knowledge snapshot (advisories/VEX/policies/trust-roots, optional DSSE sign, time anchor).
stella airgap import <bundle>Import a snapshot; --verify-only, --force, --trust-policy, --max-age-hours, --quarantine-on-failure.
stella airgap diff <base> <target>Compare two knowledge snapshots.
stella airgap statusShow current air-gap state and staleness (text/json).
stella airgap jobs {export,import,list}Manage HLC job-sync bundles for offline scenarios.

There is no stella airgap seal / stella airgap unseal command and no stella pack … group at all (deleted 2026-09-14, SPRINT_20260914_003 JEF-4). Sealing/unsealing is performed through the HTTP API described in §8.1.

Host note, 2026-09-14. §8.1 is named for the airgap-controller deployable, which retired 2026-09-11 (SPRINT_20260722_025 OK-5) and is frozen at src/__Obsoleted/AirGap/StellaOps.AirGap.Controller/. The section heading is left unchanged because four in-document links anchor to it. The /system/airgap/* paths it documents are still served — live probe 2026-09-14 returns 401 with an error body naming "service":"policy-engine" — and sealed-posture custody now lives in Platform’s platform.environment_state (/api/v1/platform/environment-state/{stateClass}/{scope}, also 401 live). Read §8.1 as the contract, not as a statement about which container answers it.

9. Changelog

DateVersionChange
2025-12-061.0.0Initial contract with enforcement logic, decision matrix, CLI integration.
2026-05-301.0.0 (reconciled)Source reconciliation: marked SUPERSEDED / NOT IMPLEMENTED. TaskRunner service deleted; no sealed_install flag, SealedInstallEnforcer, or coded exit codes exist. Corrected status-API path/scope/shape and CLI surface; added §8 documenting the shipping AirGap Controller API, Policy Engine SealedModeService, and stella airgap CLI.