phase 1 core platform

This milestone is the explicit completion gate for Phase 1. It exists because individual milestone acceptance criteria only verify their own narrow slice. A system can have all milestones marked complete and still have emergent security failures when the pieces are composed together. What individual milestone tests c

Milestone 1.5.1 — Phase 1 Security Integration Test Suite (Cross-Tenant + Auth Boundary Gate)

Status: Complete
Goal: 1.5 — Phase 1 Security Gate
Phase: 1 — Core Platform
Estimated effort: 3–4 days
ADR required: None (test suite, not design decision)


Why This Milestone Exists

This milestone is the explicit completion gate for Phase 1. It exists because individual milestone acceptance criteria only verify their own narrow slice. A system can have all milestones marked complete and still have emergent security failures when the pieces are composed together.

What individual milestone tests cannot catch:

  • M1.2.1 tests that auth middleware calls gRPC correctly.
  • M1.2.5 tests that agent verification calls auth correctly.
  • M1.2.4 tests that rate limiting calls Redis correctly.
  • None of them test that the composed middleware chain — auth → agent verification → rate limit → handler — enforces the full security model end-to-end through a real HTTP connection with a real Postgres database and real Redis.

This milestone writes and runs exactly those end-to-end security integration tests. It is the Phase 1 completion certificate.

The security model being validated:

  1. Every request without a valid token is rejected before reaching the handler.
  2. Every request with a valid token for Org A cannot access resources belonging to Org B.
  3. Revoked tokens are rejected within the documented SLA.
  4. Agents belonging to a different org are rejected, even with a valid token.
  5. Rate limits are enforced per org and return correct headers.
  6. Permission bitmap enforcement rejects insufficient permissions.

Non-Goals

  • Performance or load testing (covered in Phase 2 milestone 2.6.1)
  • Fuzzing or penetration testing (out of scope for Phase 1)
  • Testing Phase 2+ functionality (LLM forwarding, directive injection)

Branch

test/m1-5-1-security-integration-test-suite

PR Title

test(security): Phase 1 security integration test suite — Phase 1 gate (m1.5.1)


Prerequisites

All of the following must be merged before this milestone begins:

  • 1.1.7 — users + agents tables
  • 1.2.4 — rate limiting middleware
  • 1.2.5 — agent identity verification
  • 1.2.6 — request ID middleware
  • 1.4.1 — seed data and compose-test stack

Test Matrix

Category 1: Token Authentication

Test IDScenarioInputExpected
SEC-1.1No Authorization header401 MISSING_TOKEN
SEC-1.2Authorization: Bearer with empty value""401 MISSING_TOKEN
SEC-1.3Malformed token (not parseable)"not_a_token"401
SEC-1.4Valid format, token not in DB"ibex_sk_unknowntoken"401
SEC-1.5Valid token, revokedRevoke via API, then use401 within revocation SLA (default 300ms; override REVOCATION_SLA_MS)
SEC-1.6Valid token, expiredToken with expires_at = past401
SEC-1.7Valid token, activeSeed tokenContinues to next middleware

Category 2: Agent Identity Verification

Test IDScenarioInputExpected
SEC-2.1Missing X-IBEX-Agent-ID header400 MISSING_AGENT_ID
SEC-2.2X-IBEX-Agent-ID not a valid UUID"not-a-uuid"400
SEC-2.3X-IBEX-Agent-ID is a valid UUID not in DBRandom UUID403 AGENT_NOT_AUTHORIZED
SEC-2.4X-IBEX-Agent-ID belongs to Org B, token from Org ACross-org403 AGENT_NOT_AUTHORIZED
SEC-2.5Agent is pausedAgent with status="paused"403 AGENT_SUSPENDED
SEC-2.6Agent is archivedAgent with status="archived"403 AGENT_SUSPENDED
SEC-2.6bAgent is suspendedAgent with status="suspended"403 AGENT_SUSPENDED
SEC-2.7Valid token + valid agent for same orgSeed dataContinues to handler
SEC-2.8Valid token + agent, auth gRPC unavailableClose auth server503 SERVICE_DEGRADED + envelope

Category 3: Cross-Tenant Isolation via Proxy

Test IDScenarioExpected
SEC-3.1Org A token + Org A agent → request proceeds past auth200 (no LLM) or 501 (no provider)
SEC-3.2Org A token + Org B agent → rejected403 (not 404)
SEC-3.3Org B token + Org A agent → rejected403 (not 404)
SEC-3.4Response to SEC-3.2 does NOT differ in timing from SEC-3.3p95 timing delta < 50ms in CI (local target 5ms)

Category 4: Rate Limiting

Test IDScenarioExpected
SEC-4.1Requests under limitX-RateLimit-Remaining decrements correctly
SEC-4.261st request with limit=60429 RATE_LIMITED
SEC-4.3429 response has Retry-After headerValue ≤ 60, Value > 0
SEC-4.4429 response has X-RateLimit-Reset headerUnix timestamp within 60s of now
SEC-4.5Org A's rate limit does not affect Org BFire 61 reqs from Org A; Org B still gets 200
SEC-4.6Redis unavailable (closed miniredis)Request succeeds — fail-open per ADR-0015

Category 5: Permission Bitmap Enforcement

Test IDScenarioExpected
SEC-5.1Token with no permissions (permissions=0)403 INSUFFICIENT_PERMISSIONS
SEC-5.2Token with read-only permission on write endpoint403
SEC-5.3Token with full permissionsRequest proceeds

Category 6: Response Headers and Envelope Consistency

Test IDScenarioExpected
SEC-6.1All error responsesHave Content-Type: application/json
SEC-6.2All error responsesJSON body matches ErrorResponse schema
SEC-6.3All error responsesrequest_id field populated and matches X-Request-ID header
SEC-6.4All 4xx/5xxX-Request-ID header present
SEC-6.5All responsesNo Authorization or token value appears in response body

Test Infrastructure

Go
//go:build integration
 
// Test infrastructure pattern for security tests:
// Each test creates its own orgs and data and runs in isolation.
 
type securityTestEnv struct {
    proxy    *httptest.Server  // proxy under test (real middleware chain)
    auth     *grpc.Server      // real auth gRPC service
    postgres *pgxpool.Pool     // test Postgres via testcontainers
    redis    *miniredis.Miniredis
}
 
// setupTwoOrgs creates two isolated orgs with agents and tokens.
// All data is cleaned up by t.Cleanup.
func setupTwoOrgs(t *testing.T, env *securityTestEnv) (orgA, orgB testOrgContext)
 
type testOrgContext struct {
    OrgID   uuid.UUID
    AgentID uuid.UUID
    Token   string // raw PAT
}

Acceptance Criteria

  • All 35+ test cases in the matrix above pass with -tags=integration
  • SEC-3.4: p95 timing delta between cross-org denials < 50ms in CI
  • SEC-4.5: rate limits are per-org (Org B not affected by Org A's exhaustion)
  • All error responses pass SEC-6.x schema checks
  • Test suite runs in < 60 seconds in CI
  • CI gate security-integration added to required checks on main branch
  • docs/SECURITY.md updated with the security model that this suite validates

Risks

RiskLikelihoodMitigation
SEC-3.4 timing test is flaky in slow CI environmentsMediumUse relative delta (p95 of 100 measurements), not absolute threshold
Miniredis does not perfectly replicate Redis INCR + EXPIRE atomicityLowUse real Redis container for SEC-4.x tests
Test suite becomes a maintenance burdenLowTests use shared securityTestEnv; adding new scenarios is one table row

Edit on GitHub

Last updated on