Crosswake. Shell. DiagnosticExport behaviour
(crosswake v0.1.2)
View Source
Behaviour-only transport seam for the diagnostic export contract.
Crosswake.Shell.DiagnosticExport defines a fire-and-forget POST contract
for shipping typed, versioned diagnostic envelopes to a host-owned endpoint.
Transport semantics (documented — not implemented here)
- Method: POST
- Content-Type: application/json
- Endpoint: host-owned and host-configured (Crosswake does not own it)
- No response awaited (fire-and-forget)
- No Elixir HTTP-sending code ships in this module (D-01/D-03)
The actual HTTP sender is implemented by the native shell (iOS MetricKit /
Android ApplicationExitInfo) in Phase 67. This module ships the typed
envelope contract and the @callback export/1 the native shell implements.
Allowlist-by-construction redaction (D-11..D-14)
The typed Envelope and NativeDiagnostic structs are the allowlist:
they cannot represent forbidden data (raw tokens, payloads, PII). The
sanitize/1 function is fail-closed: it rejects any input that contains
a forbidden key, an unexpected key, or an out-of-enum value.
Phase 65 proof anchors
behaviour_info(:callbacks)must include{:export, 1}forbidden_keys/0⟂allowed_keys/0(disjoint; 19 forbidden keys)sanitize/1returns{:error, :redaction_failed}on invalid input- No
diagnostics.*added toBridge.Contract.commands/0 - No HTTP client dependency in the published lib
Summary
Functions
Returns the declared allowed key set (envelope fields + native_diagnostic
fields) as the documented union allowlist. Shares no key with
forbidden_keys/0.
Returns the closed exit_reason enum.
Returns the canonical 19-key forbidden set (verbatim from Chimeway.Telemetry).
Returns the closed kind enum.
Returns the closed layer enum: [:native, :web, :bridge].
Constructs an Envelope from a map or keyword list.
Constructs an Envelope, raising on failure. Used for fixture generation.
Constructs a NativeDiagnostic from a map or keyword list.
Returns the closed platform enum: [:ios, :android, :web].
Returns the canonical protocol identifier.
Maps an untrusted input map to a typed Envelope.t() or rejects it.
Returns the schema version string.
Returns the closed source enum: [:metrickit, :app_exit_info].
Converts an Envelope or NativeDiagnostic struct to a string-keyed map.
Callbacks
@callback export(Crosswake.Shell.DiagnosticExport.Envelope.t()) :: :ok | {:error, term()}
Export a typed diagnostic envelope to the host-owned endpoint.
This is a fire-and-forget POST contract. No response is awaited. The host/native shell implements this callback; Crosswake ships no Elixir HTTP-sending code.
Functions
@spec allowed_keys() :: [atom()]
Returns the declared allowed key set (envelope fields + native_diagnostic
fields) as the documented union allowlist. Shares no key with
forbidden_keys/0.
Note: sanitize/1 validates the outer input map's keys against the envelope
fields; the nested native_diagnostic map is validated against the
native-diagnostic fields when coerced into a typed NativeDiagnostic.
@spec exit_reasons() :: [atom()]
Returns the closed exit_reason enum.
@spec forbidden_keys() :: [atom()]
Returns the canonical 19-key forbidden set (verbatim from Chimeway.Telemetry).
@spec kinds() :: [atom()]
Returns the closed kind enum.
@spec layers() :: [atom()]
Returns the closed layer enum: [:native, :web, :bridge].
@spec new_envelope(map() | keyword()) :: {:ok, Crosswake.Shell.DiagnosticExport.Envelope.t()} | {:error, keyword()}
Constructs an Envelope from a map or keyword list.
Returns {:ok, %Envelope{}} on success, {:error, keyword()} on failure.
@spec new_envelope!(map() | keyword()) :: Crosswake.Shell.DiagnosticExport.Envelope.t()
Constructs an Envelope, raising on failure. Used for fixture generation.
@spec new_native_diagnostic(map() | keyword()) :: {:ok, Crosswake.Shell.DiagnosticExport.NativeDiagnostic.t()} | {:error, keyword()}
Constructs a NativeDiagnostic from a map or keyword list.
@spec platforms() :: [atom()]
Returns the closed platform enum: [:ios, :android, :web].
@spec protocol() :: String.t()
Returns the canonical protocol identifier.
@spec sanitize(map()) :: {:ok, Crosswake.Shell.DiagnosticExport.Envelope.t()} | {:error, :redaction_failed}
Maps an untrusted input map to a typed Envelope.t() or rejects it.
Fail-closed (D-14): returns {:error, :redaction_failed} when:
- input is not a map
- any key normalizes to a key in
forbidden_keys/0 - any key is outside
allowed_keys/0(unexpected key) - any enum field has an out-of-range value
- any required field is missing or invalid
Does NOT drop-and-continue. A rejected payload is better than a silently truncated partial record.
@spec schema_version() :: String.t()
Returns the schema version string.
@spec sources() :: [atom()]
Returns the closed source enum: [:metrickit, :app_exit_info].
@spec to_map( Crosswake.Shell.DiagnosticExport.Envelope.t() | Crosswake.Shell.DiagnosticExport.NativeDiagnostic.t() ) :: map()
Converts an Envelope or NativeDiagnostic struct to a string-keyed map.
Stringifies all atom values (:native → "native"), rejects nil values
and empty maps, and recurses into nested %NativeDiagnostic{} structs.
No @derive Jason.Encoder is used.