CTCL · Developers

Developer Console

Everything a client implementer needs in one place (§5.7).

Interfaces

REST + OpenAPI/openapi.json
Agent tool declaration/ai/ctcl.json
JS SDK (ESM)/sdk.js
Remote MCP/mcp — stateless Streamable HTTP: 11 tools including challenge-bound T2 attest_now (non-persistent signing) and register_instant (public KV write). No identity, enrollment, or T3/T4 authority is implied. Trigger/WakeEvent capability stays in the Temporal Port desktop app's Local MCP.
CLInot on this Web deployment — curl/SDK/MCP are the interfaces here. A CLI exists for the separate Temporal Port desktop app (ctcl-cli, github.com/kakon77777-commits/ctcl-app)
Webhook relaynot yet implemented — deliberately deferred (§9.4/§28): ranked last of the WakeEvent delivery transports pending real design for SSRF/replay/secret-management risk

Challenge-bound signed now

POST /v1/attest-now and MCP ctcl.attest_now sign a fresh CTCL edge-clock instant together with a caller-generated nonce and an opaque SHA-256 context digest. The caller cannot choose the time; this operation writes no instant to CTCL KV.

This is T2 network-synchronized reference evidence, not a T3/T4 timing authority, identity proof, or enrollment. Relying systems must pin the CTCL public key independently and check signature, nonce, context, freshness, and replay policy. See the closed response schema and verification contract.

Error codes

INVALID_TIME_VALUE400
malformed, missing, or out-of-range input value
INVALID_ATTESTATION_REQUEST400
attest-now requires only a lowercase hex nonce and SHA-256 context digest
ATTESTATION_REQUEST_TOO_LARGE413
attest-now request exceeds the 512-byte limit
UNKNOWN_ENCODING400
encoding not recognized (unix_s|unix_ms|unix_us|unix_ns|rfc3339)
INVALID_TIMEZONE400
not a valid IANA timezone name
NONEXISTENT_LOCAL_TIME400
DST spring-forward gap — this local time never occurred
AMBIGUOUS_LOCAL_TIME400
DST fall-back overlap — this local time occurred twice
UNSUPPORTED_POLICY400
invalid rate/system policy in a custom system definition
UNKNOWN_SYSTEM404
no such custom system id
UNKNOWN_GROUP404
no such Temporal Group id
UNKNOWN_WORKSPACE404
no such Shared Workspace id
UNKNOWN_PROVIDER404
no such OAuth sign-in provider
AUTH_DISABLED503
this deployment has no client id/secret configured for that provider
AUTH_DENIED400
the sign-in provider returned an error (e.g. the user cancelled)
AUTH_STATE_INVALID400
OAuth state missing/expired/reused — restart the sign-in flow
AUTH_PROVIDER_ERROR502
the OAuth provider's token or userinfo endpoint failed
NOT_AUTHENTICATED401
no active session — sign in first
FORBIDDEN403
authenticated, but not the owner of this resource
UNKNOWN_INSTANT404
no such registered instant id
UNKNOWN_TRANSFORM404
no such transform type id
REGISTRY_UNAVAILABLE503
CTCL_KV not bound on this deployment
SIGNING_DISABLED503
no Ed25519 signing key configured (CTCL_SIGN_KEY unset)
RATE_LIMITED429
over 120 requests/min for this IP on /v1/*
NOT_FOUND404
unknown route

Version policy

All routes here are v1. The response envelope shape ({ok, data, meta} / {ok:false, error, meta}) will not change within v1 — new optional fields may be added, but existing fields won't be removed or repurposed. A breaking change would ship as /v2, not a silent mutation of /v1.

Changelog

2026-10-07Added challenge-bound T2 time attestation over REST and MCP. The Ed25519 signature covers server-observed time, nonce, context digest, source and uncertainty; no caller-chosen time or CTCL KV write. This does not grant identity or production authority.
2026-08-28Registered-instant signatures (POST /v1/instants) now additionally cover a canonical digest of label+meta (§31) — closes a real gap found by an external project (CTCL-ITR) using a registered instant's signature as a third-party trust anchor: the previous instant_id|unix_ns|timescale scheme said nothing about a record's own label/meta content, so that binding rested on trusting this server, not the signature. A new, separately-labelled scheme (signature.signed_fields says which one applies per-record); nothing signed before this date is invalidated. GET /v1/now is unaffected — it carries no such payload.
2026-08-02Remote MCP Gateway (/mcp, §12.1) — stateless Streamable HTTP, 10 read/compute tools mirroring the REST API 1:1; write/Trigger/WakeEvent capability stays on the Temporal Port desktop app's Local MCP (whitepaper §12.3's read/write separation), never exposed here
2026-07-14Shared Workspaces (/v1/workspaces) + Google/GitHub sign-in (§Phase 5) — owned workspaces are protected, everything else stays accountless; QR Code on Share Instant (§6.6); every persisted resource type Ed25519-signed (§31.1); tai/gps timescales now leap-aware via the full 1972-2017 historical offset table
2026-07-12Registered instants (/v1/instants) now Ed25519-signed (§31); SDK gained monotonic() (§32), guardedNow() rollback detection (§33), offlineNow() degraded mode (§39), and a maxAgeMs staleness check in verifyInstant()
2026-07-11Constraint Planner, Semantic Resolution, Share Instant, Boundary Inspector, Temporal Groups — CommonInstant Web whitepaper P1–P6
2026-07-11Ed25519-signed instants (§31), native rate limiting (§38), table_lookup transform
2026-07-11Migrated to standalone repo (from unbounded-axiom)
2026-07-10v0.1 MVP: reference instant, convert, transform, agent tool declaration
raw version JSON