Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
112 commits
Select commit Hold shift + click to select a range
683fa6f
fix: ensure scope-based sharing logic in JetStream key construction a…
dbotwinick May 24, 2026
434921e
deps: update google.golang.org/genproto dependencies to latest versions
dbotwinick May 25, 2026
c931557
feat: add RetryPolicy + cross-workspace service task delivery
dbotwinick May 26, 2026
46c48a7
feat: improve error handling in KV operations by resolving pending sy…
dbotwinick May 26, 2026
ad78b9c
feat: implement asynchronous task assignment handling to prevent dead…
dbotwinick May 26, 2026
fa4aa83
feat: ensure typed failure responses are emitted for KV operation errors
dbotwinick May 26, 2026
0a37f58
feat: normalize body=None in proxy_http and proxy_http_async to preve…
dbotwinick May 28, 2026
d425f0a
feat: add raw downstream tap for routing correlated responses and all…
dbotwinick May 28, 2026
5ca5ca7
feat: implement CLAIM operation for task management, allowing assigne…
dbotwinick May 29, 2026
7cdc7a0
feat: implement per-identity authentication failure throttle to reduc…
dbotwinick May 29, 2026
52a36d0
feat: enhance gateway connection management with credential refresh a…
dbotwinick May 29, 2026
c5e275a
feat: add connection status query operations and response handling to…
dbotwinick May 29, 2026
04dc784
feat: add task priority support for improved dispatch ordering and fi…
dbotwinick May 31, 2026
c6166d7
feat: add Authorization field to task options and implement ClaimTask…
dbotwinick May 31, 2026
9c44831
feat: add atomic conditional write operations (SetNX, CompareAndSet, …
dbotwinick Jun 1, 2026
033a00a
feat: implement infra-coordination fast-path for WorkflowEngine acces…
dbotwinick Jun 1, 2026
87fa529
feat: implement embedded workflow store selection for PostgreSQL and …
dbotwinick Jun 1, 2026
d66d18f
feat: add pagination support to KV operations with limit and cursor o…
dbotwinick Jun 1, 2026
f364afe
feat: add PURGE_IDENTITY operation for removal-only purging of KV nam…
dbotwinick Jun 1, 2026
6c01322
feat: enhance DispatchTransformResult and TransformResult for create_…
dbotwinick Jun 2, 2026
4a86cb3
feat: add event sending capability and improve progress topic resolution
dbotwinick Jun 2, 2026
a978985
feat(kv): add atomic SetAdd/SetCard primitive across all backends
dbotwinick Jun 2, 2026
3460b23
feat(workflow): add workflow_joins store layer for fan-in joins
dbotwinick Jun 2, 2026
97a64e6
feat(workflow): add fan-in/coalesce join destination engine
dbotwinick Jun 2, 2026
f458d6b
feat(proto): add join ops, KV set primitives, and task correlation fi…
dbotwinick Jun 2, 2026
60ac01c
feat(workflow): add join deadline/timeout sweep with persisted actions
dbotwinick Jun 2, 2026
9a8f580
feat(workflow): set-mode joins via SET_ADD/SET_CARD over gRPC + SDK
dbotwinick Jun 2, 2026
04ff92f
feat: idempotent create_task for exactly-once join firing
dbotwinick Jun 2, 2026
f636189
feat(workflow): join observability ops (LIST/GET/CANCEL_JOIN)
dbotwinick Jun 2, 2026
475dcb3
docs(workflow): comprehensive Workflow Engine guide
dbotwinick Jun 2, 2026
6b860ca
feat(proto): add TaskCompletionEvent (feed-B) config
dbotwinick Jun 2, 2026
4c81db7
feat(tasks): persist correlation_id, root_task_id, completion_event
dbotwinick Jun 2, 2026
121b05a
feat: feed-B task-completion events for workflow joins
dbotwinick Jun 2, 2026
222a7d7
docs(workflow): document feed B and task correlation as implemented
dbotwinick Jun 2, 2026
8dd7ad5
chore(proto): regenerate per-message TypeScript bindings
dbotwinick Jun 3, 2026
a3548b5
Merge feat/workflow-joins: workflow fan-in/coalesce/set joins
dbotwinick Jun 3, 2026
918e2b5
feat(proxy-terminator): add tenant_id to stamp X-Auth-Tenant-ID in st…
dbotwinick Jun 18, 2026
a7b9dae
feat(gateway): mint canonical X-Auth-* identity headers on every Prox…
dbotwinick Jun 18, 2026
31fb92f
feat(gateway): complete semi-strict mTLS auth mode
dbotwinick Jun 18, 2026
e527fb5
feat(python-client): gRPC keepalive for silent-drop detection
dbotwinick Jun 18, 2026
77b56f4
feat(acl): role/group authorization with additive evaluation
dbotwinick Jun 18, 2026
f2d7c44
feat(python-client): role/group + explain_access admin convenience me…
dbotwinick Jun 18, 2026
7e718a6
fix(acl): honor op.RuleId in REVOKE (delete_acl_rule by rule_id) + ad…
dbotwinick Jun 18, 2026
6e519c7
feat(acl): on-behalf-of authorization for ACL operations
dbotwinick Jun 19, 2026
224f047
feat(auth): anonymous-cert + per-user API-key connection auth
dbotwinick Jun 19, 2026
6746b16
feat(sdk/python): add PrincipalType constants (canonical principal-ty…
dbotwinick Jun 19, 2026
802867f
fix(gateway): expand _subject_workspaces to '*' in minted X-Auth-Work…
dbotwinick Jun 20, 2026
0a9f562
feat(sdk/python): env-tunable infinite reconnect + connection-gated h…
dbotwinick Jun 20, 2026
436cedd
fix(keepalive): permit SDK streamless keepalive — stop GOAWAY too_man…
dbotwinick Jun 23, 2026
84a7f98
feat(gateway): task-msg assignee authorization + audit/log KV & TaskO…
dbotwinick Jun 24, 2026
fd78cbe
fix(proxy-sidecar): unify relay onto RelayMux for both modes — fixes …
dbotwinick Jun 24, 2026
1969fb2
fix(relaymux): broadcast IncomingMessage (Msg) to relay sub-clients
dbotwinick Jun 24, 2026
0dfbf57
fix(relaymux): route relay sub-client proxy responses back to owner
dbotwinick Jun 24, 2026
3562c18
feat(proxysidecar): tenant-relay + aggregator service-tunnel modes
dbotwinick Jun 25, 2026
5565d6c
feat(sdk): emit ClientOptions.Metadata as stream headers on Connect
dbotwinick Jun 25, 2026
ab09d98
test(gateway,state): semi-strict tenant identity + cross-backend resu…
dbotwinick Jun 25, 2026
bbc7064
feat(proxysidecar): WatchTenants snapshot_complete sentinel
dbotwinick Jun 25, 2026
4a2cf96
feat(sdk/kv): expose AuthorizationContext on KV operations
dbotwinick Jun 26, 2026
fb3f146
feat(proxysidecar): dial unix:// terminator backends
dbotwinick Jun 26, 2026
6d4dddf
feat(gateway,sdk): propagate resolved OBO subject on delivered messages
dbotwinick Jun 26, 2026
ba44415
feat(sdk): add ServiceTopic helper for workspace-less service principals
dbotwinick Jun 26, 2026
fffae90
otel: add OTLP metrics + Go runtime metrics to gateway + aetherlite
dbotwinick Jun 28, 2026
e5034d7
fix(otel): gateway traces use OTLP gRPC exporter (match meter + 4317 …
dbotwinick Jun 28, 2026
6ff4e6c
feat(kv): permit MetricsBridge principal to access the KV store
dbotwinick Jun 28, 2026
a0c36e1
fix(gateway): correct stale per-user progress topic comment
dbotwinick Jul 7, 2026
bed9744
feat(gateway): add uu:: user-broadcast topic for cross-window user ta…
dbotwinick Jul 7, 2026
351f2e6
docs: document uu:: user-broadcast channel
dbotwinick Jul 7, 2026
bfb7097
feat(sdk): add user-broadcast (uu::) send helpers
dbotwinick Jul 7, 2026
8e9c234
feat(cleanup): reap stale interactive tasks via TTL sweep
dbotwinick Jul 7, 2026
07c9070
sdk(python): create_task forwards retry_policy to CreateTaskRequest
dbotwinick Jul 11, 2026
2164ee0
feat(authproxy): internal-only /auth/verify-optional (optional-auth e…
dbotwinick Jul 16, 2026
ffddad8
fix(authproxy): /auth/verify-optional anonymous path emits identity h…
dbotwinick Jul 17, 2026
c084e73
feat(gateway): ServiceIdentity.no_pool_consumer to opt out of pool-ta…
dbotwinick Jul 17, 2026
142b6dd
feat(gateway): stale agent_startup task TTL reaper + proxysidecar age…
dbotwinick Jul 20, 2026
222d7de
fix(workflow): dispatch event handling off the receive loop (async) t…
dbotwinick Jul 20, 2026
e2d5bd0
fix(sdk/go): metric/event topic helpers must use "::" separator
dbotwinick Jul 20, 2026
c4a6843
fix(gateway): allow agent principals to publish own metrics without w…
dbotwinick Jul 20, 2026
2c8302a
feat(gateway): log task COMPLETE/FAIL outcomes (success + every rejec…
dbotwinick Jul 21, 2026
f8836f9
fix(cleanup): run TTL sweeps single-node-direct + add pool-task sweep
dbotwinick Jul 21, 2026
c3d290a
fix(orchestration): retire orchestrated_task_queue rows reliably + re…
dbotwinick Jul 22, 2026
600147e
feat(audit): scheduled retention sweep + coalesce high-volume route e…
dbotwinick Jul 22, 2026
a0b3627
fix(cleanup): wire QueueReconcileInterval into gateway/aetherlite config
dbotwinick Jul 22, 2026
368b72e
fix(router/badger): persist consumer offset after replay
dbotwinick Jul 22, 2026
b8ace47
fix(lite): harden badger/sqlite stores against connection-storm write…
dbotwinick Jul 22, 2026
e45607b
fix(router/badger): retry saveOffset on optimistic-concurrency conflict
dbotwinick Jul 22, 2026
8cf3080
fix(gateway/router): resume-or-tail user broadcast + live task-lane subs
dbotwinick Jul 22, 2026
f3c1fc4
fix(gateway/router): task-lane replays, progress resume-or-tail, badg…
dbotwinick Jul 22, 2026
c554a12
fix(router/badger): expire orphaned consumer offsets via TTL (7d defa…
dbotwinick Jul 22, 2026
2148e4c
fix(sdk/python): drop bogus KVOperation int_value field in kv_increme…
dbotwinick Jul 23, 2026
5f46445
docs: sync README/CLAUDE/CHANGELOG + docs/ with current source
dbotwinick Jul 23, 2026
e121133
docs(changelog): split unreleased 0.2.2 from released 0.2.1
dbotwinick Jul 23, 2026
2da2687
chore(version): bump Aether components to v0.2.2 and update dependencies
dbotwinick Jul 23, 2026
1fb74bc
chore(deps): update go-backpressure to v0.1.1 and normalize Go to 1.2…
dbotwinick Jul 23, 2026
5c5556b
ci: bump go-version 1.25.10 -> 1.25.12 in workflows
dbotwinick Jul 23, 2026
c5c7a59
chore(deps): include aether-api-go module in versions.yaml for versio…
dbotwinick Jul 23, 2026
60c1fd6
chore(deps): tidy go.sum across api/sdk/server after version+protobuf…
dbotwinick Jul 23, 2026
878ec81
fix(proxysidecar): don't require a workspace for the service identity
dbotwinick Jul 23, 2026
d61e28e
fix(proxysidecar): connect as a workspace-less service (support both …
dbotwinick Jul 23, 2026
9ebebcb
test(cluster): gate cluster setup on JetStream readiness, not a fixed…
dbotwinick Jul 23, 2026
ad3a390
chore(lint): clear golangci-lint findings (errcheck, staticcheck, unu…
dbotwinick Jul 23, 2026
f3a219a
fix(build): bump server/Dockerfile Go 1.25.10 -> 1.25.12 (complete th…
dbotwinick Jul 23, 2026
68d9fd2
test(proxysidecar): widen gateway-stream connect timeouts (CI -race f…
dbotwinick Jul 23, 2026
71f0535
feat(gateway/auth): dev-mode bypass for anonymous impersonable princi…
dbotwinick Jul 23, 2026
9dac809
ci: serialize integration + e2e test jobs to stop 2-core-runner flakes
dbotwinick Jul 23, 2026
fff5b10
docs(security): add the two new docker/docker cp-race advisories
dbotwinick Jul 23, 2026
f1556b7
ci(security): informational non-blocking govulncheck scan of sdk/go
dbotwinick Jul 23, 2026
708fd9a
test(cluster): widen backup-roundtrip waits for CI -race load
dbotwinick Jul 23, 2026
db1a922
test(cluster): -race-aware deadline scaling to end integration flakes
dbotwinick Jul 23, 2026
182705c
docs: correct README config/instructions + prune out-of-place proxy docs
dbotwinick Jul 23, 2026
2e8af5e
fix(acl/sqlite): parse granted_at TEXT in group/role list reads
dbotwinick Jul 23, 2026
dcd67af
feat(proto): add `noPoolConsumer` field to typescript ServiceIdentity…
dbotwinick Jul 24, 2026
03a6e7c
fix(ci): add missing `uv` dependency in version-check workflow
dbotwinick Jul 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .github/workflows/proto-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:

- uses: actions/setup-go@v5
with:
go-version: '1.25.10'
go-version: '1.25.12'

- name: Install protoc
uses: arduino/setup-protoc@v3
Expand Down
31 changes: 24 additions & 7 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:

- uses: actions/setup-go@v5
with:
go-version: '1.25.10'
go-version: '1.25.12'
cache-dependency-path: server/go.sum

- name: Run go vet
Expand All @@ -45,7 +45,7 @@ jobs:

- uses: actions/setup-go@v5
with:
go-version: '1.25.10'
go-version: '1.25.12'
cache-dependency-path: server/go.sum

- name: golangci-lint
Expand Down Expand Up @@ -128,12 +128,16 @@ jobs:

- uses: actions/setup-go@v5
with:
go-version: '1.25.10'
go-version: '1.25.12'
cache-dependency-path: server/go.sum

- name: Run integration tests
working-directory: server
run: go test -race -count=1 -tags=integration ./...
# Serialize with -p 1 -parallel 1: these integration tests spin up
# embedded NATS clusters and real sidecar runners/tunnels. Running them
# concurrently on the 2-core runner starves timing-sensitive setup
# (JetStream elections, tunnel handshakes) and causes contention flakes.
run: go test -race -count=1 -p 1 -parallel 1 -tags=integration ./...

e2e:
runs-on: ubuntu-latest
Expand All @@ -142,7 +146,7 @@ jobs:

- uses: actions/setup-go@v5
with:
go-version: '1.25.10'
go-version: '1.25.12'
cache-dependency-path: server/go.sum

# The e2e suite spawns aetherlite as a subprocess and exercises the
Expand All @@ -155,7 +159,10 @@ jobs:
working-directory: server
env:
AETHER_ALLOW_DEV_MODE: "true"
run: go test -tags=e2e -count=1 -timeout 360s ./internal/proxysidecar/integration_e2e/...
# -parallel 1: the e2e tests share one aetherlite subprocess; running the
# t.Parallel tunnel tests concurrently against the shared gateway causes
# tunnel-lifecycle races (PEER_RESET) under 2-core-runner load. Serialize.
run: go test -tags=e2e -count=1 -p 1 -parallel 1 -timeout 360s ./internal/proxysidecar/integration_e2e/...

security:
runs-on: ubuntu-latest
Expand All @@ -164,7 +171,7 @@ jobs:

- uses: actions/setup-go@v5
with:
go-version: '1.25.10'
go-version: '1.25.12'
cache-dependency-path: server/go.sum

- name: Install govulncheck
Expand All @@ -173,3 +180,13 @@ jobs:
- name: Run govulncheck
working-directory: server
run: govulncheck ./...

# Informational scan of the published Go SDK, which reaches the Docker
# orchestrator (sdk/go/orchestrators/docker) and thus CALLS the docker/docker
# vulnerabilities tracked in SECURITY.md's Known Issues. continue-on-error so
# the build stays green on those already-tracked, no-upstream-fix advisories,
# while surfacing them (and any genuinely new SDK vuln) in the CI log.
- name: Run govulncheck (SDK — informational, non-blocking)
working-directory: sdk/go
continue-on-error: true
run: govulncheck ./...
2 changes: 1 addition & 1 deletion .github/workflows/version-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
python-version: '3.12'

- name: Install dependencies
run: pip install pyyaml
run: pip install pyyaml uv

- name: Check version consistency
run: python scripts/update-versions.py --check --verbose
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ build/
/RELEASING.md
/server/coverage.out
/.run-ci-logs/
/bin/
37 changes: 35 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,42 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Aet

---

## [Unreleased]
## [0.2.2] - Unreleased

Internal builds carry a **v0.2.1** gateway/SDK version stamp; no v0.2.1 tag is published yet.
Work landed since the **v0.2.1** release (2026-05-22); not yet tagged.

### Added

- **[GATEWAY / SDK] `uu::` user-broadcast topic** for cross-window user targeting (`uu::{user_id}`). A platform→user channel carrying ordinary `MessageEnvelope` protos; only Service, WorkflowEngine, and Bridge principals may publish (`routing.go` enforces the sender-type gate). SDKs gain user-broadcast send helpers and the channel is documented.
- **[GATEWAY / AETHERLITE] OpenTelemetry OTLP metrics + Go runtime metrics** (`internal/tracing/meter.go`), gated on the same `OTEL_EXPORTER_OTLP_ENDPOINT` env var as tracing — when unset, metrics are a no-op. Both the gateway and aetherlite binaries initialize the OTLP gRPC meter alongside the existing tracer.
- **[GATEWAY] `ServiceIdentity.no_pool_consumer`** proto field lets a Service principal opt OUT of pool-task consumer routing (serve-only), so a service can connect without being enrolled as a POOL task consumer.
- **[AUTHPROXY] Internal-only `/auth/verify-optional` endpoint** — an optional-auth variant of `/auth/verify` for `ext_authz` optional-auth flows. With no credential present it passes through anonymously and emits EMPTY identity headers; a present-but-invalid credential still fails closed.
- **[PROXY SIDECAR] Tenant-relay and aggregator service-tunnel modes** for relaying sandbox tunnels through a tenant boundary, plus a `WatchTenants` `snapshot_complete` sentinel and support for dialing `unix://` terminator backends.
- **[GATEWAY / CLEANUP] Stale-task TTL sweeps.** A stale `agent_startup` pool-task reaper and a stale-interactive-task sweep (`InteractiveTaskTTL` / `InteractiveTaskCancelInterval`) auto-cancel non-terminal tasks left behind by disconnected clients; sweeps run single-node-direct so aetherlite (no leader election) reaps reliably.
- **[GATEWAY] Task COMPLETE/FAIL outcome logging.** The gateway now logs every task-op outcome — success and each rejection reason (not found, unauthorized, completeFn error) — for the COMPLETE/FAIL branches.
- **[GO SDK] `ServiceTopic` helper** for workspace-less service principals.

### Changed

- **[AETHERLITE / BADGER ROUTER] Badger message + offset retention TTLs.** The single-node Badger router now expires stored messages (default 24h, override via `AETHER_MESSAGE_RETENTION_TTL`) and orphaned per-consumer offset keys (default 7d, override via `AETHER_OFFSET_RETENTION_TTL`). Active consumers keep re-saving their offset so the TTL refreshes and the key never expires while in use; an offset for a consumer that never returns (e.g. a closed browser tab) is eventually reclaimed instead of growing without bound.
- **[GATEWAY] Broadcast/progress subscriptions use resume-or-tail semantics.** Global-user (`gu::`), user-workspace (`uw::`), user-broadcast (`uu::`), and per-user progress (`pg::`) lanes now subscribe as named resume-or-tail (exclusive) consumers, so a reconnect replays only the missed gap instead of re-delivering the whole lane; the task-message lane does a full replay on (re)connect.
- **[GATEWAY / SDK] Resolved OBO subject propagated on delivered messages** so downstream consumers can attribute a delivered message to the on-behalf-of subject rather than only the system actor.
- **[AUDIT] High-volume proxy-route event coalescing.** A bounded, sharded coalescer collapses repetitive `proxy_http_routed`-class events (e.g. per-token chat streaming) while never coalescing failures, denials, or auth/task/kv/control events, which are always audited individually. Complements the new scheduled audit-retention sweep.

### Fixed

- **[GO SDK] Metric/event topic helpers now use the `::` separator.** `MetricTopic`/`MetricWildcardTopic` and `EventTopic`/`EventWildcardTopic` emitted the legacy dot form (`metric.*` / `event.*`), which the gateway's `validateTopicFormat` rejects as `ERR_INVALID_TOPIC` — so every `SendMetric`/`SendEvent` publish was silently dropped. They now emit the `::` identity separator.
- **[GATEWAY] Agent principals can publish their own metrics without workspace WRITE.** `checkMessageSend` gated metric publishes on a per-workspace WRITE grant, so intentionally READ-only agents (e.g. sandbox agents seeded READ on their home workspace) could never emit their own token/usage metrics. An agent targeting the metric fan-in plane (`metric::*`) is now additively granted ReadWrite, realizing the "same-workspace publish is implicit" contract; cross-workspace, topic-eligibility, and negative-delta checks are unaffected.
- **[WORKFLOW] Event dispatch moved off the receive loop (`AsyncMessageHandler`).** Handling events inline on the receive loop let a synchronous KV-coordination call self-deadlock (the response needed the blocked loop), surfacing as `coalesce gate: DEADLINE_EXCEEDED`; event handling now runs asynchronously.
- **[BADGER ROUTER] Consumer-offset durability.** The router persists a consumer's offset after a replay and retries `saveOffset` on an optimistic-concurrency conflict, so offsets survive reconnects instead of being lost under contention.
- **[AETHERLITE] Connection-storm write-contention hardening** for the Badger and SQLite lite stores, reducing write contention when many clients connect at once.
- **[ORCHESTRATION / CLEANUP] `orchestrated_task_queue` retirement.** Queue rows whose task is terminal or missing are now retired reliably and orphans reconciled on a schedule (`QueueReconcileInterval`, default 5m; 0 disables).

---

## [0.2.1] - 2026-05-22

The accumulated work that shipped in the **v0.2.1** SDK/gateway version bump (Go / Python / TypeScript).

### Added

Expand Down
24 changes: 17 additions & 7 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ This project is made by scitrera.ai. Therefore, the naming involves "scitrera";
- api/ - Protobuf definitions and generated code (own Go module: `github.com/scitrera/aether/api`)
- sdk/ - Client SDKs (Go, Python, TypeScript)
- server/ - Go server (module: `github.com/scitrera/aether`)
- server/cmd/ - Main entry points (gateway, auth-proxy, migrate, cleanup, loadtest)
- server/cmd/ - Main entry points (gateway, aetherlite, auth-proxy, proxy-sidecar, workflow, migrate, cleanup, init-secrets, readiness-check, loadtest)
- server/configs/ - YAML configuration files (e.g., dev.yaml)
- server/deployments/ - Kubernetes manifests and Docker Compose files
- server/docs/ - Server documentation (quickstart, scaling, monitoring, admin API, error codes, etc.)
Expand All @@ -24,7 +24,7 @@ This project is made by scitrera.ai. Therefore, the naming involves "scitrera";
- server/scripts/ - Server dev scripts (infra, test, certs, load test)
- server/specification.md - Full system specification (v4.0, reflects actual implementation)
- server/go.mod, server/go.sum - Go module files
- server/Dockerfile - Multi-stage build for gateway, cleanup, and migrate binaries
- server/Dockerfile - Multi-stage build for gateway, cleanup, migrate, auth-proxy, init-secrets, workflow, aetherlite, and proxy-sidecar binaries
- server/Makefile - Build/test/run targets (run from server/ directory)
- scripts/ - Repo-wide scripts (compile_protos.sh)
- refs/ - Reference materials (external open source code; exclude from general scans)
Expand Down Expand Up @@ -111,7 +111,7 @@ cd server
| **Orchestration** | `server/internal/orchestration/` | Task dispatch via AMQP, claim-based delivery, profile management |
| **Admin Server** | `server/internal/admin/server.go` | REST API + embedded UI; ops server for health probes + Prometheus metrics |
| **Auth Proxy** | `server/cmd/auth-proxy/` + `server/internal/authproxy/` | Standalone auth gateway for external services (e.g., MemoryLayer) |
| **Identity Model** | `server/pkg/models/identity.go` | Seven principal types (Agent, Task, User, Orchestrator, WorkflowEngine, MetricsBridge, Bridge), topic address derivation via `ToTopic()` |
| **Identity Model** | `server/pkg/models/identity.go` | Eight principal types (Agent, Task, User, Service, Orchestrator, WorkflowEngine, MetricsBridge, Bridge), topic address derivation via `ToTopic()` |

### Topic Schema and Routing

Expand All @@ -123,11 +123,13 @@ cd server
| `tb` | `tb::{workspace}::{impl}` | Task broadcast (load-balancing) |
| `us` | `us::{user_id}::{window_id}` | User window-specific |
| `uw` | `uw::{user_id}::{workspace}` | User workspace-scoped |
| `uu` | `uu::{user_id}` | User broadcast — reaches all of a user's windows regardless of active workspace; workspace-agnostic, ordinary (non-progress) messages. Platform-principal senders only (see permission matrix). |
| `ga` | `ga::{workspace}` | Global agent broadcast |
| `gu` | `gu::{workspace}` | Global user broadcast |
| `pg` | `pg::{workspace}` | Progress updates (server-side recipient filtering) |
| `event.*` | Write: `event.{workspace}` (gateway rewrites to `event::receiver{shard}`); Subscribe (WE): `event::receiver0` | Workflow Engine fan-in; today 1 shard (`event::receiver0`) |
| `metric.*` | Write: `metric.{workspace}` (gateway rewrites to `metric::receiver{shard}`); Subscribe (MB): `metric::receiver0` | Metrics Bridge fan-in; today 1 shard (`metric::receiver0`) |
| `event::` | Write: `event::{workspace}` (gateway rewrites to `event::receiver{shard}`); Subscribe (WE): `event::receiver0` | Workflow Engine fan-in; today 1 shard (`event::receiver0`). A legacy `event.*` (dot) form is rejected as an invalid topic prefix. |
| `metric::` | Write: `metric::{workspace}` (gateway rewrites to `metric::receiver{shard}`); Subscribe (MB): `metric::receiver0` | Metrics Bridge fan-in; today 1 shard (`metric::receiver0`) |
| `tk` | `tk::{workspace}::{task_id}::events` (TaskEvent stream) and `tk::{workspace}::{task_id}::msg` (per-task chat) | Per-task lanes; SUBJECT sessions auto-subscribe for the task's lifetime. Task-message lane uses full replay; user broadcast lanes (`gu`/`uw`/`uu`) and `pg` use resume-or-tail. |
| `br` | `br::{impl}::{spec}` | Bridge (cross-workspace messaging integration) |

### Connection Flow
Expand Down Expand Up @@ -185,7 +187,9 @@ An active gRPC stream connection represents both the distributed lock for that i

Cross-workspace sends are blocked: workspace-scoped principals cannot target topics in other workspaces. Bridges are cross-workspace by design (no workspace component) and check ACL per-message against the target workspace.

**Cross-workspace event/metric broadcast:** Sending to `event.*` or `metric.*` in another workspace requires `capability/event_broadcast` or `capability/metric_broadcast` ACL permission. Sending to the sender's own native workspace is implicitly permitted.
**User-broadcast (`uu::{user_id}`):** A workspace-agnostic channel that reaches every one of a user's windows regardless of which workspace each window is viewing (the non-progress complement to `pg::us::{user}`). Because the topic carries no workspace segment, the workspace ACL cannot gate it, so authorization is by principal type: **only Service, WorkflowEngine, and Bridge principals may publish** (`enforceTopicPermissions`). Users, Agents, Tasks, and Orchestrators are denied and must reach a user via `us::`/`uw::`/progress or task ownership. Users subscribe to their own `uu::` topic on connect.

**Cross-workspace event/metric broadcast:** Sending to `event::` or `metric::` topics in another workspace requires `capability/event_broadcast` or `capability/metric_broadcast` ACL permission. Sending to the sender's own native workspace is implicitly permitted.

**Metric payloads are structured:** `METRIC` messages must carry a `Metric` proto payload (fields: `trace_id`, `entries` [{`name`, `kind`, `qty`}], `metadata`, `client_timestamp_ms`). All entries are additive deltas; negative `qty` requires the `capability/metric_credit` ACL permission. See spec Section 4.5 for details and error codes.

Expand Down Expand Up @@ -224,6 +228,12 @@ PostgreSQL is used for persistent features that gracefully degrade when unavaila

Schema is managed by embedded migrations in `server/migrations/` that auto-run on startup.

### Observability
Both `gateway` and `aetherlite` export OpenTelemetry traces and metrics via OTLP gRPC (`internal/tracing/`: `InitTracer`, `InitMeter`, `NewLogBridge`), gated on the standard `OTEL_EXPORTER_OTLP_ENDPOINT` env var (no-op when unset; OTLP gRPC default port 4317). This is independent of the admin ops server's Prometheus `/metrics` endpoint (port 9090).

### Background Cleanup / Reconcile
The cleanup service (`internal/cleanup/`, wired in both `gateway` and `aetherlite`) runs periodic sweeps: orphaned `orchestrated_task_queue` reconciliation (`QueueReconcileInterval`, default 5m), audit-log retention sweep, stale `agent_startup` / interactive-task TTL reapers, and a stale regular pool-task sweep (`CancelStalePoolTasks`). On single-node AetherLite these run leader-gated/single-node-direct.

## Horizontal Scaling

- **Stateless Design:** All state in Redis and PostgreSQL. Gateway instances share nothing.
Expand All @@ -235,7 +245,7 @@ Schema is managed by embedded migrations in `server/migrations/` that auto-run o
### Deployment Options
- **Kubernetes:** `server/deployments/k8s/gateway/` — Deployment, Service, Ingress, ConfigMap, cert-manager
- **Docker Compose:** `server/deployments/docker-compose/multi-instance.yaml` — 3 instances + nginx
- **Dockerfile:** `server/Dockerfile` — Multi-stage build, non-root user, ports 50051/9090/31880 (build from repo root: `docker build -f server/Dockerfile .`)
- **Dockerfile:** `server/Dockerfile` — Multi-stage build, non-root user, ports 50051/9090/31880/8080 (build from repo root: `docker build -f server/Dockerfile .`)

## Client SDKs

Expand Down
Loading
Loading