ADORSYS-GIS / ADORSYS-GIS/lightbridge-governance

[Story]: Authenticated OTLP ingestion on otel.ai.camer.digital (AuthConfig #3)

未關閉
#13 2 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視
governance user-story
主要語言
Rust
星號
1
分支
2
平均合併
13 小時 13 分鐘
30 天內合併 PR
110

描述

### Story Statement

As a **Foundry agent operator**,
I want to **push OTLP telemetry to an authenticated public endpoint**,
so that **agent activity is recorded in governance without exposing an open ingestion endpoint to the internet.**

### Real Intent

This is the first governance work that touches shared production infrastructure. The feature is ordinary — accept OTLP, authenticate it. The risk is concentrated in one place, and this story exists as much to contain that risk as to deliver the feature.

### Background and Context

There is no ingestion path for telemetry originating outside the cluster.

The shape is already proven here: an Authorino AuthConfig calling a first-party Rust service's resolve endpoint over a shared secret is the ADR-0047 pattern, in production today. What is new is a **third host-indexed AuthConfig** and a **public** host.

### ⚠️ The hazard this story must not trigger

**An AuthConfig `sharedSecretRef` pointing at a Secret that does not exist makes the AuthConfig fail readiness, which 404s the *entire gateway* — every host, every route.**

This is not hypothetical. It is the OPA-removal outage, recorded in `docs/migrations/2026-hetzner-cutover.md`, where pruning an app cascade-deleted the `lightbridge-opa-auth` Secret and took the gateway down.

The mitigation is ordering, not care:

> **The Secret must exist and report `SecretSynced=True` before the AuthConfig references it — in a separate, earlier change.**

### Source of truth (links)

- Epic: #6
- ⚠️ **Blocked by #8** (tenancy spike). Settle the isolation story before writing code.
- Depends on: #11 (`/internal/v1/resolve`), #10 (credentials)
- The outage this must not repeat: `docs/migrations/2026-hetzner-cutover.md`
- Pattern precedent: ai-helm ADR-0047; existing collector notes in `charts/core-gateway/templates/otel.yaml`

### Acceptance Criteria

#### Functional
- [ ] Given a registered integration with a valid credential, when it pushes OTLP to `otel.ai.camer.digital`, then the telemetry is accepted and attributed to its tenant and application.
- [ ] Given telemetry is accepted, when it is processed, then it fans out to metrics, logs and traces.
- [ ] Given a revoked credential, when it pushes, then the request is rejected within the documented cache TTL.

#### Negative / Edge Cases
- [ ] Given **no** credential, when a request is made to the public host, then it is rejected. Verified explicitly — this endpoint is on the internet.
- [ ] Given an invalid or malformed credential, when a request is made, then it is rejected with a single opaque error.
- [ ] Given the governance resolve service is down, when a request arrives, then it is **denied**, not accepted. Fail closed.
- [ ] Given a malformed OTLP payload, when it arrives, then it is rejected without affecting other traffic.

#### Non-Functional
- [ ] ⚠️ **Gateway availability is unaffected throughout rollout.** The AuthConfig change is applied only after its Secret reports `SecretSynced=True`, and a tested revert is ready before it is applied.
- [ ] The added per-request cost of a third host-indexed AuthConfig is **measured** before and after — it is paid by all gateway traffic, including traffic unrelated to Foundry.
- [ ] TLS for `otel.ai.camer.digital` comes from the in-chart namespace ACME **HTTP-01** issuer. ⚠️ **Not** `cert-cloudflare`: `ai.camer.digital` is NS-delegated to Route53, and a DNS-01 challenge there reports `Presented: true` and then stalls forever on "not yet propagated" while cert-manager writes the TXT into the Cloudflare zone. `dig +short NS` first.
- [ ] `X-Scope-OrgID` may be recorded, but is **documented as non-isolating** — it does nothing on our single-tenant LGTM stack.

### Out of Scope

- **Enabling LGTM multi-tenancy.** Decision 3: not now.
- Privacy modes and normalization — related but separate story.
- The integration-setup page.
- Any claim of tenant isolation in customer-facing docs. Whatever #8 decides is what gets said, exactly.

### Dependencies and Blockers

- ⚠️ **Blocked by #8.**
- Depends on #11 being deployed and reachable *before* the AuthConfig references it.
- **Strict ordering, and it is the whole risk mitigation:**
1. Governance resolve service deployed and reachable.
2. Shared-secret Secret created, `SecretSynced=True` **verified**.
3. *Then* the AuthConfig.

Each step is its own change. Do not collapse them.

### Assumptions

1. **Authorino handles a third host-indexed AuthConfig without meaningful overhead.** ⚠️ Measure — do not assume. It is evaluated on every request to the gateway.
2. The ADR-0047 resolve pattern carries over unchanged.
3. OTLP over HTTP is sufficient; gRPC can follow if asked for.
4. A public ingestion endpoint is acceptable given per-integration revocable credentials and rate limiting.

### Implementation Notes

Guidance, not gospel:

- Sequence over care. The ordering above is what prevents the outage; "review carefully" is not a mitigation.
- Have the revert prepared and *tested* before applying the AuthConfig, not written afterwards.
- Rate-limit the public endpoint. Authentication is not a defence against volume.
- Cilium is default-deny; ingress to the collector needs an explicit allow — the observability stack has already lost time to exactly this (`accepted_spans=0` with everything apparently healthy).

### Test Expectations

- Unit: payload validation, credential extraction.
- Integration: authenticated push succeeds; unauthenticated rejected; revoked rejected; resolve-down denies.
- **Manual, in a non-production gateway first:** apply the AuthConfig and confirm other hosts still serve. This is the rehearsal for the failure mode that matters.
- Latency measured on unrelated gateway traffic, before and after.

### Verification evidence

*To be completed on delivery.*

Required:
- `SecretSynced=True` shown for the shared secret **before** the AuthConfig was applied — with timestamps establishing the order.
- Proof that other gateway hosts kept serving during and after the AuthConfig change.
- The negative tests, named individually.
- Before/after latency on unrelated gateway traffic.
- The certificate issued, and confirmation it came from the HTTP-01 issuer.

### Human accountable owner

@stephane-segning

### AI Usage Declaration

Drafting this story, Refining acceptance criteria

### Human verification completed

- [x] I checked the story against the source of truth
- [x] I confirmed the acceptance criteria
- [x] I reviewed the implementation approach
- [x] I documented remaining risks
- [x] I am the accountable owner and accept responsibility for this story.

貢獻指南

開啟貢獻指南

評估

這個 Issue 還沒有評估資料。

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。