IBEX Harness
DocsBenchmarksBlogChangelogRoadmap
GitHub
IBEX Harness

Documentation

Architecture Decision RecordsADR-0002: Repository foundation bootstrapADR-0003: Branch protection and merge policyADR-0004: Protobuf and code generation policyADR-0005: Postgres migration strategyADR-0006: Auth protobuf contract (`ibex.auth.v1`)ADR-0007: Auth token validation implementationADR-0008: Security scanning and CI quality gatesADR-0009: Permission bitmap layoutADR-0010: Cryptography policyADR-0011: Proxy auth gRPC client and middlewareADR-0012: Proxy request normalization (OpenAI chat)ADR-0013: Proxy input validation and stable error envelopeADR-0014: Core domain migration sequencingADR-0015: Proxy rate limit skeleton (Phase 1)ADR-0016: Proxy agent identity verification (Phase 1)ADR-0017: Request ID and trace context strategy (Phase 1)ADR-0018: Graceful shutdown contract (Phase 1)ADR-0019: OpenTelemetry provider configuration (Phase 1)ADR-0020: Shared package boundaries — `packages/config` and `packages/apierror`ADR-0021: Prometheus Metric Catalog (Phase 1)ADR-0022: Health check contract (Phase 1)ADR-0023: Docs site architecture (Phase 1.5)ADR-0024: Benchmark data publishing modelADR-0025: LLM provider abstractionADR-0026: OpenAI client designADR-0027: Streaming dual-write strategyADR-0028: Auth cache designADR-0029: Token revocation propagation via Redis pub/subADR-0030: Directive versioning strategyADR-0031: System prompt injection strategyADR-0032: Session data model and retentionADR-0033: ClickHouse llm_traces schema and retentionADR-0034: Proxy overhead performance measurement methodologyADR-0035: Chat Idempotency-Key Redis dedupeADR-0038: Context assembly service design and gRPC contractADR-0039: Proxy Postgres ownership for session and directive storesADR-0040: Anthropic provider adapterADR-0041: Model capability registryADR-0042: Self-hosted OpenAI-compatible LLM adapterADR-0043: Tokenizer registry architectureADR-0044: Non-streaming response pipelineADR-0045: Streaming response transformationADR-0046: Embedder interface and profile registryADR-0047: Memory temporal validity foundationADR-0048: Memory multi-label categoriesADR-0049: Memory relationship graph readinessADR-0050: MCP server skeleton (transport, auth, audit)ADR-0051: Local LGTM observability stack (Phase 2.5 exit pull-forward)ADR-0052: Memory schema v2 expand (HNSW, quality columns)ADR-0053: Vector store abstraction and composite scoring v2
ADRs›ADR-0030: Directive versioning strategy
ADRs

ADR-0030: Directive versioning strategy

Accepted — immutable directive_versions with active_version_id pointer; one config per agent; SHA-256 content_hash; 32KB cap; org RLS.

ADR-0030: Directive versioning strategy

  • Status: Accepted (schema in 2.3.1; read path in 2.3.2)
  • Date: 2026-07-23
  • Authors: IBEX Harness team
  • Milestone: 2.3.1 Directive migrations

Context

An agent directive is the system-level instruction IBEX injects into every LLM request for that agent. Operators need safe updates with rollback and an audit trail. Mutable in-place edits lose history and complicate cache invalidation on the proxy hot path.

Phase 2 needs a minimal agent-scoped schema. A fuller marketplace-oriented model (named org-level directives, installs, tags) remains documented in DATABASE_SCHEMA.md but is out of scope until later phases.

Decision

  1. Immutable versions: directive_versions rows are append-only. Content is never updated after insert. Rollback = repoint directives.active_version_id to a prior version.
  2. One config per agent: UNIQUE(agent_id) on directives. Each agent has at most one directive configuration row; version history hangs off that row.
  3. Injection mode: injection_mode enum (system_first, system_append, user_prepend) stored on directives. Behavior is implemented in 2.3.3.
  4. Content integrity: content_hash is SHA-256 of content (application-computed). CHECKs enforce non-empty content and octet_length(content) <= 32768 (32KB byte cap).
  5. Tenant isolation: Both tables have org_id, ENABLE + FORCE ROW LEVEL SECURITY, NULLIF-safe org setting, and service-account bypass via ibex_core.rls_org_visible — matching the agents pattern. Ownership is structural via composite FKs (agent_id, org_id) and (directive_id, org_id), plus a trigger ensuring active_version_id belongs to the same directive and org (single-column FK with ON DELETE SET NULL for cascade-safe cleanup).
  6. Append-only versions: ibex_app has only SELECT, INSERT on directive_versions (no UPDATE/DELETE); a BEFORE UPDATE trigger rejects mutations. Parent ON DELETE CASCADE cleanup runs as table owner.
  7. Deferred circular FK: active_version_id FK is added NOT VALID then VALIDATE after directive_versions exists.
  8. Proxy read path: Deferred to 2.3.2. This ADR covers persistence only.

Consequences

  • Migration 000009_create_directives applies the Phase 2 subset under ibex_core.
  • Cache keys in 2.3.2 can key on (org_id, agent_id, active_version_id) / content_hash without worrying about silent content mutation.
  • Marketplace / multi-directive-per-org features require a later expand migration; they must not break the one-config-per-agent contract without an explicit ADR.

Alternatives considered

  1. Mutable single-row directive — simpler schema; no rollback/audit. Rejected.
  2. Git-like parent_version_id DAG — useful for forks; unnecessary for Phase 2 linear history. Deferred with marketplace schema.
  3. Org-level named directives with agent installs — matches long-term DATABASE_SCHEMA.md; too large for Goal 2.3. Deferred.

Was this page helpful?

Edit on GitHub

Last updated on

PreviousADR-0029: Token revocation propagation via Redis pub/subNextADR-0031: System prompt injection strategy

On this page

  • Context
  • Decision
  • Consequences
  • Alternatives considered
0%