Pharos Framework

← Back

Compiled Host Contract

Pharos can build an app artifact that is served by an executable host generated as part of pharos build, or served directly by the Pharos binary for static-pages app targets.

These are the current minimal contracts.

Pharos compiled hosts sit on top of a lower executable host/runtime process boundary. Pharos adds app-specific assembly, serving, artifact shaping, and state behavior on top of that boundary.

Contract IDs

pharos.compiled_host.static_pages.v1

pharos.compiled_host.dynamic_app.v1

Scope

These contracts are intentionally narrow.

static_pages.v1 covers a static app target whose artifact is fully materialized under the selected --build-dir.

dynamic_app.v1 covers a small stateful app target whose host owns:

  • a local JSON state file
  • a small HTML page surface
  • a JSON state API
  • form POST actions
  • optional multipart/form-data parsing for bundle-based dynamic hosts

They do not yet cover:

  • multi-surface dynamic applications
  • auth/session flows
  • richer maintenance mutations
  • auth/session flows

App Manifest Shape

The app manifest declares:

{
  "runtime": {
    "host_profile": "static-pages | dynamic-app"
  },
  "fixtures": {
    "integration_fixture": "data/framework/<integration-fixture>.json"
  }
}

Meaning:

  • host_profile tells Pharos whether the app uses the static-pages direct-artifact contract or the dynamic-app native runtime contract
  • source manifests for both static-pages and dynamic-app may omit compiled_entrypoint
  • after P3.8, dynamic-app apps must not depend on runtime/<app_id>_native_host
  • static-pages apps are served directly from the finalized artifact by the Pharos native runtime path rather than through an app-owned checked-in shell host
  • app-owned host bundles are no longer part of the canonical runtime story for dynamic-app

Generated Host Surface

When a generated host artifact exists, the executable surface must support:

  • --build-dir PATH
  • --summary
  • --seed-state
  • --serve
  • --host HOST
  • --port PORT

At the process/runtime layer, Pharos expects deterministic argv dispatch and explicit filesystem/report behavior. Hidden subprocess or network behavior is out of contract unless a higher runtime contract declares it directly.

Behavior:

  • --seed-state: returns a JSON seed acknowledgement
  • --summary: returns JSON with route/surface/workflow counts
  • --serve: serves the built artifact directory over HTTP
  • dynamic_app.v1 additionally owns a local JSON state file and simple POST mutations

For the current native runtime path, static-pages apps do not require a generated checked-in executable host in source control and the finalized native-built artifact records an empty compiled_entrypoint.

Bundle-Based Dynamic Host Surface

When a dynamic-app provides an app-owned host entry and companion bundle directory under runtime/<app-host>.d/, Pharos stages that source bundle into the built compiled host and exposes a stable helper surface for common HTTP/runtime behavior, multipart parsing, integrations, generated surfaces, and workflow logic.

Current core helper functions:

  • pharos_normalize_base_path BASE_PATH
  • pharos_cookie_path
  • pharos_prefix_path PATH
  • pharos_strip_base_path PATH
  • pharos_apply_base_path_html HTML
  • pharos_url_decode VALUE
  • pharos_cookie_value COOKIE_HEADER COOKIE_NAME
  • pharos_form_value FORM_BODY FIELD_NAME
  • pharos_query_value QUERY_STRING FIELD_NAME
  • pharos_http_response STATUS CONTENT_TYPE BODY [EXTRA_HEADERS]
  • pharos_http_stream_begin STATUS CONTENT_TYPE [EXTRA_HEADERS]
  • pharos_http_redirect LOCATION [EXTRA_HEADERS]
  • pharos_builtin_route_dispatch_response STATE_PATH REQUEST_TARGET REQUEST_HEADERS METHOD ROUTED_PATH [USER_JSON] [SUBSCRIPTION_SCOPE_JSON]
  • pharos_event_stream_response STATE_PATH REQUEST_TARGET REQUEST_HEADERS [USER_JSON] [SUBSCRIPTION_SCOPE_JSON]
  • pharos_request_is_framework_csrf_exempt METHOD ROUTED_PATH
  • pharos_webhook_route_response STATE_PATH REQUEST_TARGET REQUEST_HEADERS ROUTED_PATH REQUEST_CONTENT_TYPE REQUEST_BODY_PATH
  • pharos_event_stream_rows STATE_PATH SINCE_ID LIMIT [SUBSCRIPTION_SCOPE_JSON] [FILTERS_JSON]
  • pharos_event_stream_emit_rows STATE_PATH SINCE_ID LIMIT [SUBSCRIPTION_SCOPE_JSON] [FILTERS_JSON]
  • pharos_state_append_audit_event STATE_PATH EVENT_KIND [PAYLOAD_JSON]
  • pharos_state_append_workflow_execution_event STATE_PATH EVENT_KIND [PAYLOAD_JSON]
  • pharos_content_type_for_file FILE_PATH
  • pharos_serve_common_asset ROUTED_PATH ARTIFACT_DIR MANIFEST_PATH

Current helper functions:

  • pharos_multipart_extract_text BODY_FILE CONTENT_TYPE FIELD_NAME
  • pharos_multipart_extract_file BODY_FILE CONTENT_TYPE FIELD_NAME OUTPUT_PATH

These helpers are the formal dynamic_app.v1 surface for:

  • base-path-aware routing and HTML rewriting
  • cookie, form, and query parsing
  • HTTP response, connection-close streaming response, and redirect emission
  • framework-owned reserved runtime routes, SSE event transport, and inbound webhook dispatch
  • framework-owned audit/workflow event publication helpers for dynamic hosts
  • common static/media/manifest asset serving
  • multipart form fields and uploaded files in template-based hosts

Native Listener Request/Response Boundary

The native Pharos listener owns a distinct forwarding and fail-closed boundary in front of compiled app hosts.

That boundary is an implementation seam, not a desired permanent divergence point. Validate native listener behavior and compiled-host behavior together in normal local testing.

Native-owned behavior includes:

  • request line parsing
  • newline-normalized forwarded headers
  • default request metadata when headers are absent
  • plain-text fallback responses for native-owned failures
  • 502 Bad Gateway fail-closed behavior when compiled app execution fails or returns no response bytes

That boundary is tracked explicitly in native-request-response-parity.md so request parsing and fallback response defaults do not drift silently from the compiled-host contract.

Preferred local convergence check:

scripts/check.sh native-compiled-flow

Artifact Manifest Fields

The built app manifest includes:

  • host_profile
  • compiled_entrypoint
  • compiled_host_contract
  • compiled_host_capabilities
  • process_runtime_contract
  • process_runtime_capabilities
  • integration_fixture

Current values:

compiled_host_contract: "pharos.compiled_host.static_pages.v1"

or

compiled_host_contract: "pharos.compiled_host.dynamic_app.v1"

Example capabilities for a bundle-based dynamic host:

  • local_json_state
  • html_routes
  • json_state_api
  • form_post_actions
  • base_path_routing
  • cookie_query_form_helpers
  • http_response_helpers
  • static_media_asset_routes
  • multipart_form_fields
  • multipart_file_uploads
  • builtin_runtime_routes
  • realtime_sse_transport
  • integration_webhook_routes

Pharos also writes a compiled host sidecar manifest at:

  • <compiled_entrypoint>.manifest.json when a generated compiled host artifact exists

That sidecar is the runtime-checked process contract Pharos validates before executing a generated native host artifact.

Event Stream Contract Additions

The reserved runtime route GET /_pharos/events/ is the framework-owned SSE surface for compiled dynamic hosts.

Current query parameters:

  • since
  • limit
  • timeout
  • source
  • event_kind
  • resource_id
  • trace_id
  • app-defined scope selectors such as tenant_id

Current event frame payload fields:

  • stream_id
  • source
  • event_kind
  • created_at
  • user_id
  • business_id
  • tenant_id
  • resource_kind
  • resource_id
  • replay_trace_id
  • payload_json

This keeps subscription transport, row shaping, and audit/workflow publication owned by Pharos while allowing app templates to provide only scope decisions and app-specific UI behavior.

Webhook Route Contract Additions

The reserved runtime route POST /_pharos/webhooks/<endpoint_id>/ is the framework-owned inbound webhook surface for compiled dynamic hosts.

Current behavior:

  • resolves endpoint contracts from the built app manifest and declared integration_fixture
  • accepts JSON payloads only
  • verifies HMAC signatures and timestamp freshness when the endpoint contract requires them
  • records webhook receipts into the app runtime state ledger
  • appends framework-owned audit events for accepted and rejected webhook deliveries
  • is CSRF-exempt through the framework helper surface for reserved webhook routes only

This keeps signature verification, receipt persistence, and operator-visible inbound integration evidence in Pharos while allowing apps to opt in declaratively through an integration fixture.

Current Proof Target

The checked static proof target is:

  • apps/static_app_template

The checked dynamic proof target is:

  • apps/dynamic_app_template

Both targets have no Python runtime entrypoint. Pharos builds a native host target for them, and app outputs should converge on that native-host delivery path rather than splitting between compiled-host and direct static runtime modes.

Current Boundary

Pharos discovers demo and product apps as standalone app roots through pharos.app.json instead of built-in website target cases. The active launcher/runtime path uses the native Pharos binary for listener ownership, static app serving, shared-runtime routing, and dropped-in app discovery. UCAL still uses an app-owned compiled entrypoint for request handling.

Pharos still owns the higher-level app assembly/runtime layer in the shell dispatcher today. The current shared shell split is recorded in ../operations/runtime-surface-ownership.md and is organized around six sourced runtime surfaces plus the dispatcher:

  • scripts/pharos_runtime.sh as the canonical shared dispatcher
  • runtime/pharos_app_runtime_layer.sh for app discovery, path resolution, and shared runtime dispatch helpers
  • runtime/pharos_data_runtime_layer.sh for migrations, seed/verify/apply helpers, and the relational runtime bridge
  • runtime/pharos_generated_surface_layer.sh for generated surface shaping helpers
  • runtime/pharos_integration_runtime_layer.sh for integration delivery and webhook state helpers
  • runtime/pharos_ops_runtime_layer.sh for operator-facing config/probe/report helpers
  • runtime/pharos_workflow_runtime_layer.sh for workflow execution and replay helpers

On top of that split, Pharos still owns:

  • app discovery through pharos.app.json
  • artifact materialization
  • compiled-host generation for dynamic Pharos app targets
  • release/package operations