Authentication¶
The ingest API authenticates the caller per request and authorizes per (partner_id, warehouse_id) pair. The schemes match the conventions used elsewhere on the FG.AI platform — mTLS in production, API key in dev/test, HMAC-SHA256 over body for inbound webhooks.
Schemes¶
Direction |
Environment |
Scheme |
|---|---|---|
Caller into FG.AI WMS |
Production |
mTLS |
Caller into FG.AI WMS |
Dev / test |
API key |
FG.AI WMS webhook into the caller |
All |
HMAC-SHA256 over raw body |
mTLS (production)¶
The caller presents a client certificate at the TLS handshake. FG.AI WMS resolves the certificate thumbprint to a row in the partner registry. The handshake authenticates; the partner registry authorizes — a handshake-valid certificate that is not in the registry is rejected with 401.
Self-signed certificates are not accepted in production. Certificates must chain to a CA that FG.AI has explicitly enrolled. Onboarding includes a CA-bundle exchange between FG.AI and the partner.
API key (dev / test only)¶
Authorization: Bearer <key>
Acceptable for dev and test only. Production partners must turn off bearer-token acceptance via the partner registry. A production receiver that falls back to bearer-token authentication is a misconfiguration.
Dev keys rotate on a 90-day cadence, matching DotID ADR-0021. Compromised keys are rotated immediately; the old key is invalidated.
HMAC-SHA256 (webhooks)¶
FG.AI WMS signs every outbound webhook body with a per-partner shared secret:
X-FGAI-Signature: sha256=<hex>
The receiving side must:
Read the raw request body before parsing.
Compute
HMAC-SHA256(secret, raw_body).Constant-time compare against the header value.
Reject with
401on mismatch.
The HMAC secret is provisioned through the partner registry. Rotation is supported via a dual-secret window (typical: 24h) during which both old and new secrets are accepted.
partner_id format¶
partner_id carries the source system code and the tenant code:
{source-system-code}-TENANT-{tenant-code}
Examples:
ACME-TENANT-A
ACME-TENANT-B
LEGACY-WMS-TENANT-001
NSWMS-TENANT-PROD
A multi-tenant upstream uses one partner_id per source-side tenant. A FlexSync connector pushing on behalf of one customer’s NetSuite WMS tenant uses one partner_id for that connector-tenant pair; a different customer is a different partner_id.
Do not overload partner_id with environment, warehouse, or integration-instance information. Those belong in the partner registry record or in the request meta block.
Warehouse scoping¶
A partner_id is registered with one or more allowed_warehouses. Calls that touch a warehouse not in the allowed list are rejected with 403. The PDP enforces this on every mutation.
The scoping is checked against the warehouse_id (or warehouse_source_id) in the request payload. A POST /inventory/movements for WH-Tokyo-02 from a credential allowed only on WH-Tokyo-01 returns 403 Forbidden with a type URL identifying the cross-warehouse credential error.
Multi-warehouse partners — common for FlexSync connectors and SI integrations — register the full set of allowed warehouses on the same partner_id. Single-warehouse partners list one warehouse.
Independence from interactive user JWTs¶
These partner credentials are entirely separate from the Keycloak JWTs that authenticate interactive users in the FlexGalaxy console (see DotID — API authentication and JWT validation). The ingest API does not accept user JWTs; it is strictly a service-to-service trust path.
When a human operator releases a quarantined item through the FlexGalaxy console, the operator’s user JWT is what FG.AI records in the audit log alongside the action. The upstream system has no knowledge of that operator’s identity unless it subscribes to the master.normalization-conflict resolution webhook.
Multiple credentials per partner¶
A partner_id may have multiple active credentials simultaneously — typically a primary production cert and a rotation-window successor cert. The partner registry supports up to two concurrent credentials per partner_id to allow seamless certificate rotation, matching the access-key dual-window pattern.
A third concurrent credential is rejected on registration. Rotate the old one out before adding new.
Audit and traceability¶
Every authenticated request produces an audit-log entry with partner_id, request path, timestamp, and trace_id (W3C traceparent header propagated end-to-end). Authentication failures are logged separately under iam.IngestAuthnFailed with severity according to the failure mode (cert chain failure: HIGH; expired API key: MEDIUM; HMAC mismatch on webhook: HIGH).