docs(rules): document http/ and outbound/ packages + admin controller
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -23,7 +23,7 @@ These paths intentionally stay flat (no `/environments/{envSlug}` prefix). Every
|
|||||||
| `/api/v1/agents/register`, `/refresh`, `/{id}/heartbeat`, `/{id}/events` (SSE), `/{id}/deregister`, `/{id}/commands`, `/{id}/commands/{id}/ack`, `/{id}/replay` | Agent self-service; JWT-bound. |
|
| `/api/v1/agents/register`, `/refresh`, `/{id}/heartbeat`, `/{id}/events` (SSE), `/{id}/deregister`, `/{id}/commands`, `/{id}/commands/{id}/ack`, `/{id}/replay` | Agent self-service; JWT-bound. |
|
||||||
| `/api/v1/agents/commands`, `/api/v1/agents/groups/{group}/commands` | Operator fan-out; target scope is explicit in query params. |
|
| `/api/v1/agents/commands`, `/api/v1/agents/groups/{group}/commands` | Operator fan-out; target scope is explicit in query params. |
|
||||||
| `/api/v1/agents/config` | Agent-authoritative config read; JWT → registry → (app, env). |
|
| `/api/v1/agents/config` | Agent-authoritative config read; JWT → registry → (app, env). |
|
||||||
| `/api/v1/admin/{users,roles,groups,oidc,license,audit,rbac/stats,claim-mappings,thresholds,sensitive-keys,usage,clickhouse,database,environments}` | Truly cross-env admin. Env CRUD URLs use `{envSlug}`, not UUID. |
|
| `/api/v1/admin/{users,roles,groups,oidc,license,audit,rbac/stats,claim-mappings,thresholds,sensitive-keys,usage,clickhouse,database,environments,outbound-connections}` | Truly cross-env admin. Env CRUD URLs use `{envSlug}`, not UUID. |
|
||||||
| `/api/v1/catalog`, `/api/v1/catalog/{applicationId}` | Cross-env discovery is the purpose. Env is an optional filter via `?environment=`. |
|
| `/api/v1/catalog`, `/api/v1/catalog/{applicationId}` | Cross-env discovery is the purpose. Env is an optional filter via `?environment=`. |
|
||||||
| `/api/v1/executions/{execId}`, `/processors/**` | Exchange IDs are globally unique; permalinks. |
|
| `/api/v1/executions/{execId}`, `/processors/**` | Exchange IDs are globally unique; permalinks. |
|
||||||
| `/api/v1/diagrams/{contentHash}/render`, `POST /api/v1/diagrams/render` | Content-addressed or stateless. |
|
| `/api/v1/diagrams/{contentHash}/render`, `POST /api/v1/diagrams/render` | Content-addressed or stateless. |
|
||||||
@@ -81,6 +81,7 @@ ClickHouse is shared across tenants. Every ClickHouse query must filter by `tena
|
|||||||
- `RoleAdminController` — CRUD `/api/v1/admin/roles`.
|
- `RoleAdminController` — CRUD `/api/v1/admin/roles`.
|
||||||
- `GroupAdminController` — CRUD `/api/v1/admin/groups`.
|
- `GroupAdminController` — CRUD `/api/v1/admin/groups`.
|
||||||
- `OidcConfigAdminController` — GET/POST `/api/v1/admin/oidc`, POST `/test`.
|
- `OidcConfigAdminController` — GET/POST `/api/v1/admin/oidc`, POST `/test`.
|
||||||
|
- `OutboundConnectionAdminController` — `/api/v1/admin/outbound-connections`. GET list / POST create / GET `{id}` / PUT `{id}` / DELETE `{id}` / POST `{id}/test` / GET `{id}/usage`. RBAC: list/get/usage ADMIN|OPERATOR; mutations + test ADMIN.
|
||||||
- `SensitiveKeysAdminController` — GET/PUT `/api/v1/admin/sensitive-keys`. GET returns 200 or 204 if not configured. PUT accepts `{ keys: [...] }` with optional `?pushToAgents=true`. Fan-out iterates every distinct `(application, environment)` slice — intentional global baseline + per-env overrides.
|
- `SensitiveKeysAdminController` — GET/PUT `/api/v1/admin/sensitive-keys`. GET returns 200 or 204 if not configured. PUT accepts `{ keys: [...] }` with optional `?pushToAgents=true`. Fan-out iterates every distinct `(application, environment)` slice — intentional global baseline + per-env overrides.
|
||||||
- `ClaimMappingAdminController` — CRUD `/api/v1/admin/claim-mappings`, POST `/test`.
|
- `ClaimMappingAdminController` — CRUD `/api/v1/admin/claim-mappings`, POST `/test`.
|
||||||
- `LicenseAdminController` — GET/POST `/api/v1/admin/license`.
|
- `LicenseAdminController` — GET/POST `/api/v1/admin/license`.
|
||||||
@@ -134,7 +135,7 @@ ClickHouse is shared across tenants. Every ClickHouse query must filter by `tena
|
|||||||
|
|
||||||
## security/ — Spring Security
|
## security/ — Spring Security
|
||||||
|
|
||||||
- `SecurityConfig` — WebSecurityFilterChain, JWT filter, CORS, OIDC conditional
|
- `SecurityConfig` — WebSecurityFilterChain, JWT filter, CORS, OIDC conditional. `/api/v1/admin/outbound-connections/**` GETs permit OPERATOR in addition to ADMIN (defense-in-depth at controller level); mutations remain ADMIN-only.
|
||||||
- `JwtAuthenticationFilter` — OncePerRequestFilter, validates Bearer tokens
|
- `JwtAuthenticationFilter` — OncePerRequestFilter, validates Bearer tokens
|
||||||
- `JwtServiceImpl` — HMAC-SHA256 JWT (Nimbus JOSE)
|
- `JwtServiceImpl` — HMAC-SHA256 JWT (Nimbus JOSE)
|
||||||
- `OidcAuthController` — /api/v1/auth/oidc (login-uri, token-exchange, logout)
|
- `OidcAuthController` — /api/v1/auth/oidc (login-uri, token-exchange, logout)
|
||||||
@@ -151,6 +152,23 @@ ClickHouse is shared across tenants. Every ClickHouse query must filter by `tena
|
|||||||
|
|
||||||
- `JarRetentionJob` — @Scheduled 03:00 daily, per-environment retention, skips deployed versions
|
- `JarRetentionJob` — @Scheduled 03:00 daily, per-environment retention, skips deployed versions
|
||||||
|
|
||||||
|
## http/ — Outbound HTTP client implementation
|
||||||
|
|
||||||
|
- `SslContextBuilder` — composes SSL context from `OutboundHttpProperties` + `OutboundHttpRequestContext`. Supports SYSTEM_DEFAULT (JDK roots + configured CA extras), TRUST_ALL (short-circuit no-op TrustManager), TRUST_PATHS (JDK roots + system extras + per-request extras). Throws `IllegalArgumentException("CA file not found: ...")` on missing PEM.
|
||||||
|
- `ApacheOutboundHttpClientFactory` — Apache HttpClient 5 impl of `OutboundHttpClientFactory`. Memoizes clients per `CacheKey(trustAll, caPaths, mode, connectTimeout, readTimeout)`. Applies `NoopHostnameVerifier` when trust-all is active.
|
||||||
|
- `config/OutboundHttpConfig` — `@ConfigurationProperties("cameleer.server.outbound-http")`. Exposes beans: `OutboundHttpProperties`, `SslContextBuilder`, `OutboundHttpClientFactory`. `@PostConstruct` logs WARN on trust-all and throws if configured CA paths don't exist.
|
||||||
|
|
||||||
|
## outbound/ — Admin-managed outbound connections (implementation)
|
||||||
|
|
||||||
|
- `crypto/SecretCipher` — AES-GCM symmetric cipher with key derived via HMAC-SHA256(jwtSecret, "cameleer-outbound-secret-v1"). Ciphertext format: base64(IV(12 bytes) || GCM output with 128-bit tag). `encrypt` throws `IllegalStateException`; `decrypt` throws `IllegalArgumentException` on tamper/wrong-key/malformed.
|
||||||
|
- `storage/PostgresOutboundConnectionRepository` — JdbcTemplate impl. `save()` upserts by id; JSONB serialization via ObjectMapper; UUID arrays via `ConnectionCallback`. Reads `created_by`/`updated_by` as String (= users.user_id TEXT).
|
||||||
|
- `OutboundConnectionServiceImpl` — service layer. Tenant bound at construction via `cameleer.server.tenant.id` property. Uniqueness check via `findByName`. Narrowing-envs guard: rejects update that removes envs while rules reference the connection (rulesReferencing stubbed in Plan 01, wired in Plan 02). Delete guard: rejects if referenced by rules.
|
||||||
|
- `controller/OutboundConnectionAdminController` — REST controller. Class-level `@PreAuthorize("hasRole('ADMIN')")` defaults; GETs relaxed to ADMIN|OPERATOR. Extracts acting user id from `SecurityContextHolder.authentication.name`, strips "user:" prefix. Audit via `AuditCategory.OUTBOUND_CONNECTION_CHANGE`.
|
||||||
|
- `dto/OutboundConnectionRequest` — Bean Validation: `@NotBlank` name, `@Pattern("^https://.+")` url, `@NotNull` method/tlsTrustMode/auth. Compact ctor throws `IllegalArgumentException` if TRUST_PATHS with empty paths list.
|
||||||
|
- `dto/OutboundConnectionDto` — response DTO. `hmacSecretSet: boolean` instead of the ciphertext; `authKind: OutboundAuthKind` instead of the full auth config.
|
||||||
|
- `dto/OutboundConnectionTestResult` — result of POST `/{id}/test`: status, latencyMs, responseSnippet (first 512 chars), tlsProtocol/cipherSuite/peerCertSubject (protocol is "TLS" stub; enriched in Plan 02 follow-up), error (nullable).
|
||||||
|
- `config/OutboundBeanConfig` — registers `OutboundConnectionRepository`, `SecretCipher`, `OutboundConnectionService` beans.
|
||||||
|
|
||||||
## config/ — Spring beans
|
## config/ — Spring beans
|
||||||
|
|
||||||
- `RuntimeOrchestratorAutoConfig` — conditional Docker/Disabled orchestrator + NetworkManager + EventMonitor
|
- `RuntimeOrchestratorAutoConfig` — conditional Docker/Disabled orchestrator + NetworkManager + EventMonitor
|
||||||
|
|||||||
@@ -78,7 +78,22 @@ paths:
|
|||||||
- `AppSettings`, `AppSettingsRepository` — per-app-per-env settings config and persistence. Record carries `(applicationId, environment, …)`; repository methods are `findByApplicationAndEnvironment`, `findByEnvironment`, `save`, `delete(appId, env)`. `AppSettings.defaults(appId, env)` produces a default instance scoped to an environment.
|
- `AppSettings`, `AppSettingsRepository` — per-app-per-env settings config and persistence. Record carries `(applicationId, environment, …)`; repository methods are `findByApplicationAndEnvironment`, `findByEnvironment`, `save`, `delete(appId, env)`. `AppSettings.defaults(appId, env)` produces a default instance scoped to an environment.
|
||||||
- `ThresholdConfig`, `ThresholdRepository` — alerting threshold config and persistence
|
- `ThresholdConfig`, `ThresholdRepository` — alerting threshold config and persistence
|
||||||
- `AuditService` — audit logging facade
|
- `AuditService` — audit logging facade
|
||||||
- `AuditRecord`, `AuditResult`, `AuditCategory`, `AuditRepository` — audit trail records and persistence
|
- `AuditRecord`, `AuditResult`, `AuditCategory` (enum: `INFRA, AUTH, USER_MGMT, CONFIG, RBAC, AGENT, OUTBOUND_CONNECTION_CHANGE, OUTBOUND_HTTP_TRUST_CHANGE`), `AuditRepository` — audit trail records and persistence
|
||||||
|
|
||||||
|
## http/ — Outbound HTTP primitives (cross-cutting)
|
||||||
|
|
||||||
|
- `OutboundHttpClientFactory` — interface: `clientFor(context)` returns memoized `CloseableHttpClient`
|
||||||
|
- `OutboundHttpProperties` — record: `trustAll, trustedCaPemPaths, defaultConnectTimeout, defaultReadTimeout, proxyUrl, proxyUsername, proxyPassword`
|
||||||
|
- `OutboundHttpRequestContext` — record of per-call TLS/timeout overrides; `systemDefault()` static factory
|
||||||
|
- `TrustMode` — enum: `SYSTEM_DEFAULT | TRUST_ALL | TRUST_PATHS`
|
||||||
|
|
||||||
|
## outbound/ — Admin-managed outbound connections
|
||||||
|
|
||||||
|
- `OutboundConnection` — record: id, tenantId, name, description, url, method, defaultHeaders, defaultBodyTmpl, tlsTrustMode, tlsCaPemPaths, hmacSecretCiphertext, auth, allowedEnvironmentIds, createdAt, createdBy (String user_id), updatedAt, updatedBy (String user_id). `isAllowedInEnvironment(envId)` returns true when allowed-envs list is empty OR contains the env.
|
||||||
|
- `OutboundAuth` — sealed interface + records: `None | Bearer(tokenCiphertext) | Basic(username, passwordCiphertext)`. Jackson `@JsonTypeInfo(use = DEDUCTION)` — wire shape has no discriminator, subtype inferred from fields.
|
||||||
|
- `OutboundAuthKind`, `OutboundMethod` — enums
|
||||||
|
- `OutboundConnectionRepository` — CRUD by (tenantId, id): save/findById/findByName/listByTenant/delete
|
||||||
|
- `OutboundConnectionService` — create/update/delete/get/list with uniqueness + narrow-envs + delete-if-referenced guards. `rulesReferencing(id)` stubbed in Plan 01 (returns `[]`); populated in Plan 02 against `AlertRuleRepository`.
|
||||||
|
|
||||||
## security/ — Auth
|
## security/ — Auth
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user