Product documentation
Product API configuration
Generated reference for the oauthy.* configuration bound by Product API.
Product API configuration
The customer-plane management API (resource server): FGA, DSAR, audit export, capability entitlement, multi-issuer token validation, and the idp-facade.
oauthy.applications.hub
Owner: product-api · Source: servers/product-api/src/main/kotlin/com/devnow/productapi/applications/HubApplicationsClient.kt
| Property | Type | Default | Description |
|---|---|---|---|
oauthy.applications.hub.base-url | String | "http://thoryn-hub:8080" | |
oauthy.applications.hub.service-identity-token-path | String | "/var/run/secrets/tokens/hub-applications-facade" |
oauthy.audit-export
Owner: product-api · Source: servers/product-api/src/main/kotlin/com/devnow/productapi/compliance/audit/AuditExportStorageConfiguration.kt
SSO-78 — audit-export storage properties.
| Property | Type | Default | Description |
|---|---|---|---|
oauthy.audit-export.s3.bucket | String | "" | |
oauthy.audit-export.s3.region | String | "" | |
oauthy.audit-export.s3.key-prefix | String | "audit-export" | |
oauthy.audit-export.local.base-dir | String | System.getProperty("java.io.tmpdir") + "/oauthy-audit-export" | Filesystem directory used by LocalFsAuditExportStore. |
oauthy.audit.internal.k8s
Owner: product-api · Source: servers/product-api/src/main/kotlin/com/devnow/productapi/audit/internal/AuditInternalSecurityConfig.kt
Configuration properties for the K8s SA-token-authenticated audit ingestion endpoint.
| Property | Type | Default | Description |
|---|---|---|---|
oauthy.audit.internal.k8s.enabled | Boolean | false | Defaults to false so unit / integration tests don't drag the K8s JWKS into the test classpath. |
oauthy.audit.internal.k8s.issuer | String | "https://kubernetes.default.svc.cluster.local" | SSO-1477 — the expected iss claim. |
oauthy.audit.internal.k8s.jwks-uri | String | "https://kubernetes.default.svc/openid/v1/jwks" | |
oauthy.audit.internal.k8s.audience | String | "product-api" | |
oauthy.audit.internal.k8s.ca-path | String | "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" | SSO-1468 — path to the PEM CA bundle whose certificate(s) sign the cluster API server's serving certificate. |
oauthy.audit.internal.k8s.token-path | String | "/var/run/secrets/kubernetes.io/serviceaccount/token" | SSO-1471 — path to the projected ServiceAccount token presented as a Bearer credential on the JWKS discovery fetch. |
oauthy.audit.internal.k8s.connect-timeout | Duration | Duration.ofSeconds(2) | SSO-1468 — connect timeout for the JWKS HTTP fetch. |
oauthy.audit.internal.k8s.read-timeout | Duration | Duration.ofSeconds(2) | SSO-1468 — read timeout for the JWKS HTTP fetch. |
oauthy.capability
Owner: product-api · Source: servers/product-api/src/main/kotlin/com/devnow/productapi/capability/CapabilityEntitlementProperties.kt
SSO-1863 (Phase 3; ADR 2026-07-01-hub-product-agnostic-platform.md) — product-api's per-family enablement policy as operator config (oauthy.capability.*), lifted out of the hardcoded CapabilityFamilyPolicy literal so no product-family na...
| Property | Type | Default | Description |
|---|---|---|---|
oauthy.capability.families | Map<String, CapabilityPolicy> | DEFAULT_FAMILY_POLICY | operator-supplied coarse-family → enable policy. |
oauthy.capability.default-new-tenant-families | Set<String> | DEFAULT_NEW_TENANT_FAMILIES | the family set a brand-new tenant is entitled to. |
oauthy.dsar
Owner: product-api · Source: servers/product-api/src/main/kotlin/com/devnow/productapi/dsar/DsarStorageConfiguration.kt
DSAR bundle-storage properties (SSO-97).
| Property | Type | Default | Description |
|---|---|---|---|
oauthy.dsar.s3.bucket | String | "" | |
oauthy.dsar.s3.region | String | "" | |
oauthy.dsar.s3.key-prefix | String | "dsar" | |
oauthy.dsar.local.base-dir | String | System.getProperty("java.io.tmpdir") + "/oauthy-dsar" | Filesystem directory used by LocalFsDsarStore. |
oauthy.dsar.fanout
Owner: product-api · Source: servers/product-api/src/main/kotlin/com/devnow/productapi/dsar/DsarFanoutProperties.kt
Configuration for the DSAR orchestrator's fan-out to peer services (SSO-97).
| Property | Type | Default | Description |
|---|---|---|---|
oauthy.dsar.fanout.hub-base-url | String | "http://localhost:8080" | |
oauthy.dsar.fanout.identity-service-base-url | String | "http://localhost:8081" | |
oauthy.dsar.fanout.product-api-base-url | String | "http://localhost:8082" | |
oauthy.dsar.fanout.service-account-token | String | "" | Bearer token presented to peers on GET /admin/dsar/{sub}. |
oauthy.erasure
Owner: product-api · Source: servers/product-api/src/main/kotlin/com/devnow/productapi/erasure/ErasureProperties.kt
Configuration for the GDPR Art.
| Property | Type | Default | Description |
|---|---|---|---|
oauthy.erasure.grace-window | Duration | Duration.ofDays(7) | Two-phase grace window between deactivate and hard-erase. |
oauthy.erasure.max-hold-window | Duration | Duration.ofDays(90) | Maximum time a hold may stand before the request is DEFERRED + escalated. |
oauthy.erasure.lock-ttl | Duration | Duration.ofSeconds(60) | Redis per-request lock TTL — bounds the orchestrator's drive. |
oauthy.erasure.sweep-cron | String | "0 11 * * * *" | Cron for the re-consult / advance sweep. |
oauthy.erasure.veto-callback-timeout | Duration | Duration.ofSeconds(5) | SSO-2510 — per-veto-client callback timeout for com.devnow.productapi.erasure.hold.RpCallbackHoldProvider. |
oauthy.fga
Owner: product-api · Source: servers/product-api/src/main/kotlin/com/devnow/productapi/fga/FgaProperties.kt
FGA configuration (oauthy.fga.*), owned by product-api (ADR 2026-07-15-fine-grained-authorization-fga.md, epic SSO-1889 + SSO-1901).
| Property | Type | Default | Description |
|---|---|---|---|
oauthy.fga.model.max-object-types | Int | 100 | Maximum number of object types a single model may define. |
oauthy.fga.model.max-relations-per-type | Int | 50 | Maximum number of relations a single object type may define. |
oauthy.fga.model.max-model-bytes | Int | 128 * 1024 | Maximum serialized model size, in bytes (128 KiB). |
oauthy.fga.model.max-rewrite-nesting-depth | Int | 10 | Maximum nesting depth of a relation's userset-rewrite tree (union / intersection / exclusion) — SSO-2576. |
oauthy.fga.check.max-depth | Int | 10 | Rewrite / userset / tupleToUserset recursion depth. |
oauthy.fga.check.max-nodes | Int | 1000 | Total tuple-expansion steps per check — the fanout / DoS budget. |
oauthy.fga.check.max-fanout | Int | 100 | Rows read per single object#relation expansion. |
oauthy.fga.check.max-batch-size | Int | 50 | Maximum number of checks a single batch POST /check may carry. |
oauthy.fga.check.cache.ttl-seconds | Long | 60 | |
oauthy.fga.limits.max-tuples-per-tenant | Long | 1_000_000 | Maximum number of relation tuples a single tenant may store. |
oauthy.fga.limits.max-writes-per-request | Int | 100 | Maximum writes + deletes a single POST /tuples may carry. |
oauthy.fga.limits.max-import-tuples-per-request | Int | 5_000 | Maximum tuples a single bulk POST /tuples:import may carry (SSO-1954). |
oauthy.fga.list-objects.max-depth | Int | 10 | Reverse-expansion BFS depth (hops out from the subject). |
oauthy.fga.list-objects.max-nodes | Int | 1_000 | Total reverse-lookup steps per request — the expansion / DoS budget. |
oauthy.fga.list-objects.max-fanout | Int | 100 | Rows read per single reverse lookup (one subject descriptor's edges). |
oauthy.fga.list-objects.max-candidates | Int | 500 | Maximum distinct candidate objects of the requested type collected before confirmation. |
oauthy.fga.list-objects.max-results | Int | 100 | Maximum objects a single response may carry, and the ceiling on the request's own limit. |
oauthy.fga.list-objects-export.max-objects | Int | 50_000 | maxObjects is the hard ceiling on candidate objects scanned per job: hitting it ends the scan with truncated: true (the honest "export too large" signal — the same prefix posture the interactive endpoint's truncated flag has). |
oauthy.fga.list-objects-export.scan-batch-size | Int | 1_000 | scanBatchSize is the DISTINCT keyset-scan page size. |
oauthy.fga.list-objects-export.ttl-hours | Long | 24 | ttlHours is how long a completed export's result stays downloadable. |
oauthy.fga.list-objects-export.stale-after-minutes | Long | 60 | staleAfterMinutes is when an in-flight (PENDING/RUNNING) job is considered abandoned (its node died) and may be reclaimed so the one-active-export slot is not stuck forever. |
oauthy.hooks.test-delivery
Owner: product-api · Source: servers/product-api/src/main/kotlin/com/devnow/productapi/hooks/HookTestDeliveryProperties.kt
SSO-2144 — configuration for the per-tenant abuse cap on the hook test-delivery endpoint (POST /api/v1/hooks/{id}/test, SSO-2102).
| Property | Type | Default | Description |
|---|---|---|---|
oauthy.hooks.test-delivery.rate-limit.limit | Long | 10 | Maximum test deliveries a single tenant may fire within window. |
oauthy.hooks.test-delivery.rate-limit.window | Duration | Duration.ofMinutes(1) | The fixed window the limit applies over. |
oauthy.hub
Owner: product-api · Source: servers/product-api/src/main/kotlin/com/devnow/productapi/config/MultiIssuerValidationConfig.kt
SSO-1521 — properties for multi-issuer validation.
| Property | Type | Default | Description |
|---|---|---|---|
oauthy.hub.issuer | String | required | |
oauthy.hub.platform-domain | String | required | the tenant-subdomain suffix, leading-dot included (OAUTHY_TENANCY_PLATFORM_DOMAIN, staging .hub.stg.thoryn.org). |
oauthy.hub.in-cluster-jwks-uri | String | "http://thoryn-hub:8080/oauth2/jwks" | |
oauthy.hub.issuer-cache-ttl-millis | Long | TrustedTenantIssuers.DEFAULT_CACHE_TTL_MILLIS | positive+negative cache TTL for the slugExists lookup; a freshly-registered tenant validates within this window (ADR §4, ≈60 s). |
oauthy.hub.trust-test-issuers | Boolean | false | SSO-2146 (SSO-1887 S8) — the per-tenant test/sandbox-mode gate. |
oauthy.hub.enforce-tnt-iss-consistency | Boolean | false | SSO-2285 (defence-in-depth from the SSO-2283 audit) — the tnt <-> iss consistency gate. |
oauthy.idp-facade
Owner: product-api · Source: servers/product-api/src/main/kotlin/com/devnow/productapi/loginexperience/IdpFacadeProperties.kt
SSO-1926 / SSO-1928: configuration for the IdP-facade's server-to-server calls to identity-service's /internal/tenants/{tenantId}/[] surface (ADR 2026-07-14-idp-frontend-tenant-facade.md).
| Property | Type | Default | Description |
|---|---|---|---|
oauthy.idp-facade.identity-service-base-url | String | "http://localhost:8081" | identity-service base URL. |
oauthy.idp-facade.token-path | String | "/var/run/secrets/tokens/identity-facade" | On-disk path of product-api's projected Kubernetes ServiceAccount token for the facade surface (audience identity-tenant-facade), mounted by the chart at /var/run/secrets/tokens/identity-facade. |
oauthy.organizations.invitation
Owner: product-api · Source: servers/product-api/src/main/kotlin/com/devnow/productapi/organizations/OrganizationInvitationEmailProperties.kt
SSO-2261: configuration for the B2B organization-invitation email.
| Property | Type | Default | Description |
|---|---|---|---|
oauthy.organizations.invitation.accept-base-url | String | "" | Public origin of the console that hosts the invitation-accept landing page, e.g. |
oauthy.product-api.internal-auth
Owner: product-api · Source: servers/product-api/src/main/kotlin/com/devnow/productapi/internalauth/InternalEndpointAuthProperties.kt
SSO-2321 — configuration for authenticating product-api's /internal/[] server-to-server surface with projected Kubernetes ServiceAccount tokens.
| Property | Type | Default | Description |
|---|---|---|---|
oauthy.product-api.internal-auth.mode | Mode | Mode.DETECT | detect (default) — validate-and-log-only; the request is ALWAYS allowed through regardless of the token's presence or validity. |
oauthy.product-api.internal-auth.exempt-paths | List<String> | listOf("/internal/claims-enrichment") | /internal/[] path prefixes that are NEVER subject to the SA-token check (always allowed, never enforced). |
oauthy.token-claims
Owner: product-api · Source: servers/product-api/src/main/kotlin/com/devnow/productapi/tokenclaims/TokenClaimsModels.kt
SSO-1904 (slice B) — tunables for the claims-in-token capability.
| Property | Type | Default | Description |
|---|---|---|---|
oauthy.token-claims.enrichment-url | String | "http://thoryn-product-api:8082/internal/claims-enrichment" | The URL product-api registers with the hub as the client's claims webhook when the toggle is enabled. |
oauthy.token-claims.max-response-bytes | Int | 65536 | Product-api-side ceiling on the serialized claims object returned by the enrichment endpoint. |
oauthy.token-claims.timestamp-tolerance-seconds | Long | 300 | Accepted clock skew, in seconds, between the hub's X-Thoryn-Timestamp and this pod's clock (both directions). |
oauthy.token-claims.elevated-scope-cache-ttl-seconds | Long | 10 | Short TTL (seconds) for the PIM/entitlement active-scope Redis cache (ElevatedScopeCache, SSO-1321/1322). |
Every property above is set as a YAML key under application.yml or, equivalently, as an environment variable using Spring's relaxed binding (oauthy.hub.platform-client-ids -> OAUTHY_HUB_PLATFORM_CLIENT_IDS). A _required_ default means the service will not start until the value is supplied.