Skip to content

Activity and customer export API

Pilot v1; not a stable SDK. Reviewed 22 September 2026.

ophiolite.activity/1 includes event ID, project ID, kind, authenticated actor ID, run ID, optional diagnostic trace ID, server UTC recorded time, evidence category, coverage profile and typed event data. Server kinds are operation.requested, operation.completed, operation.failed and operation.unconfirmed. Exact references use project, asset and revision; a run ID is distinct from a revision. Completed scalar events include parameters/unit, lineage and runtime measurements. CPU seconds describe calculation process time. Peak RSS is the process lifetime high-water mark, not per-operation allocation. No raw arrays appear in the event.

consumer.applied is explicitly client-reported. Its data includes exact reference, binding ID, application/connector versions, follow/pin/copy and phase timings. Profile /1 retains its historical inclusive apply_ms, including notification waiting. Profile /2 uses optional timings; missing timings mean unavailable, not zero. Duplicate IDs with different content fail. Identical heartbeats update the last-seen row without appending another event. The server verifies current project access and that the exact revision is available; it does not trust a caller-supplied actor identity. Default retained consumer-event limit per project: 10,000, configurable from 100 to 1,000,000.

Browser POST /api/activity/list requires the existing session, allowed origin and CSRF header. /api/activity/export accepts the same body and returns a page of NDJSON with X-Next-Cursor. The list response contains stream ID, events, next cursor, up to 200 recent consumer reports and declared coverage.

{"project_id":"YOUR_PROJECT","after":0,"limit":200}

OAuth connectors use POST /api/v1/connector/activity/list; project-read API delegates use POST /api/v1/projects/{project_id}/activity. Both recheck access. Machine delegates do not fall back to browser cookies. Continue with next_cursor until an empty page. Cursors are monotonically increasing within a journal stream; gaps are normal and do not imply missing project events. A replacement journal gets a different stream ID and requires explicit export restart.

POST /api/v1/connector/activity/report with the connector bearer credential:

{
"reference":{"project_id":"YOUR_PROJECT","asset_id":"YOUR_ASSET","revision":"7"},
"binding_id":"a083f048-98eb-4b65-984b-b48139b371d0",
"event_id":"333a127f-e938-4fe4-9d57-21298f4ae681",
"profile":"qgis-scalar-consumer/2",
"application_version":"4.2.2",
"connector_version":"0.4.0",
"mode":"follow",
"timings":{"notification_wait_ms":15000,"download_ms":200,"prepare_ms":10,"gui_apply_ms":35}
}

This illustrative payload does not grant publication permission or certify human inspection. Tokens are never embedded in events. Capability profiles for additional hosts require implementation and host qualification before claiming support.

Platform provides python -m project_gateway.activity_export --help. A token file, or workload configuration, project, checkpoint and JSONL directory or PostgreSQL destination are required. SQL connection credentials come from OPHIOLITE_EXPORT_POSTGRES_DSN, kept outside the browser and repository. Export commits to the destination before advancing the checkpoint. SQL uses (stream_id,event_id) as its idempotency key and stores the complete JSONB event. JSONL uses one atomically replaced segment per event. Do not share a checkpoint between concurrent exporters.

Watch mode reloads the token file and pauses on failure. Current five-minute API delegates require renewal and remain tied to their browser session. Revocation prevents future reads, not access to already exported copies. Customer SQL password rotation does not alter checkpoint identity.

The integration repository’s deployment/observability/ includes tested local Jaeger/Collector/PostgreSQL containers and a configurable customer OTLP exporter. These are single-node examples, not production HA, SSO, backups or retention qualification. Optional diagnostic queues can lose spans; durable scientific lineage and operation journals are independent of tracing.

User guide.

For unattended export, IT provisions a confidential OIDC client with the Workspace audience and client-credentials grant. Its exact issuer/subject must map to a native project viewer with no compute grant. Gateway workload_clients maps that client ID to {"subject":"EXACT_SUBJECT","projects":["PROJECT_ID"]}. This restricts access; it does not replace native project permissions. Only the activity read endpoint accepts these workload credentials. Each request checks introspection, issuer, audience, client, subject, expiry, identity state and project access.

Use --workload-config /private/workload.json instead of --token-file. The mode-0600 JSON file contains exactly issuer, client_id, client_secret. The exporter renews in memory before expiry and reloads rotated configuration. It requires no browser. Disable the mapped identity or revoke its project grant to stop reads. The deployment examples include a supervised service and customer-owned SQL sink.

OPHIOLITE_CONSUMER_RETENTION_DAYS defaults to 0 (no pruning). Positive days prune old delivery observations and presence on project access, at most once a minute. Inactive projects are pruned when accessed again. Minimal identity/fingerprint tombstones remain to reject altered replays. Scientific operation events and publication intents are never pruned by this option.

Pages expose pruned_through and consumer_retention_days. A newly encountered export gap requires --accept-retained-history; it cannot restore deleted events. Export regularly before retention expires. Customer sink retention is independent.

OPHIOLITE_TRACE_SAMPLE_RATIO (0–1, default 1) controls parent-based diagnostic sampling. No trace ID is advertised for an unsampled operation; durable events remain. Jaeger’s example OPHIOLITE_TRACE_TTL defaults to 168h. Viewer links use OPHIOLITE_TRACE_VIEWER_URL, reachable from the user’s browser and separately secured by customer IT.

A new consumer report has its own trace linked to the producing trace where known. Client phase durations are attributes, not backdated server spans. Server-derived publication_trace_id, publication_recorded_at, and server_receipt_lag_ms correlate the report with the committed revision. Lag includes waiting/reporting; it is not screen latency. Optional W3C trace_context is correlation metadata, never a credential. Repeated heartbeats create no additional diagnostic traces.