531 lines
17 KiB
YAML
531 lines
17 KiB
YAML
openapi: 3.0.3
|
|
info:
|
|
title: as4-411 Directory and Resolver API
|
|
description: |
|
|
Standards-aware directory and discovery service for AS4, SS7, and messaging gateways.
|
|
See [data-model](../architecture/data-model.md) and [resolution-algorithm](../architecture/resolution-algorithm.md).
|
|
version: 0.1.0
|
|
|
|
servers:
|
|
- url: /api
|
|
description: API base path
|
|
|
|
tags:
|
|
- name: Resolver
|
|
description: Gateway-facing resolution
|
|
- name: Admin
|
|
description: Directory management
|
|
- name: System
|
|
description: Health and metrics
|
|
|
|
paths:
|
|
# --- Resolver API (gateway-facing) ---
|
|
/v1/resolve:
|
|
post:
|
|
tags: [Resolver]
|
|
summary: Resolve identifiers to routing directives
|
|
description: |
|
|
For ISO 20022 FI-to-FI, use service = `iso20022.fi` and action = `credit.transfer`, `fi.credit.transfer`, `payment.status`, `payment.cancellation`, `resolution.of.investigation`, `statement`, or `notification`.
|
|
Profile returned: `as4.fifi.iso20022.v1`.
|
|
operationId: resolve
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/ResolveRequest" }
|
|
example:
|
|
identifiers:
|
|
- type: as4.partyId
|
|
value: BANKUS33XXX
|
|
scope: BIC
|
|
serviceContext:
|
|
service: iso20022.fi
|
|
action: credit.transfer
|
|
responses:
|
|
"200":
|
|
description: Resolution result
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/ResolveResponse" }
|
|
example:
|
|
primary:
|
|
target_protocol: as4
|
|
target_address: https://as4.bankus.com/fi
|
|
transport_profile: as4.fifi.iso20022.v1
|
|
security:
|
|
signRequired: true
|
|
encryptRequired: true
|
|
keyRefs: [vault://certs/bankus/iso20022]
|
|
service_context:
|
|
service: iso20022.fi
|
|
action: credit.transfer
|
|
resolution_trace:
|
|
- source: internal directory
|
|
"400":
|
|
description: Invalid request
|
|
"503":
|
|
description: Resolver unavailable
|
|
|
|
/v1/bulk-resolve:
|
|
post:
|
|
tags: [Resolver]
|
|
summary: Batch resolve multiple requests
|
|
operationId: bulkResolve
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [requests]
|
|
properties:
|
|
requests:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/ResolveRequest" }
|
|
responses:
|
|
"200":
|
|
description: Batch resolution results
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
results:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/ResolveResponse" }
|
|
traceId: { type: string, format: uuid }
|
|
|
|
# --- System ---
|
|
/v1/health:
|
|
get:
|
|
tags: [System]
|
|
summary: Health check
|
|
operationId: health
|
|
responses:
|
|
"200":
|
|
description: Service healthy
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status: { type: string, enum: [ok, degraded] }
|
|
version: { type: string }
|
|
checks: { type: object }
|
|
|
|
/v1/metrics:
|
|
get:
|
|
tags: [System]
|
|
summary: Prometheus metrics
|
|
operationId: metrics
|
|
responses:
|
|
"200":
|
|
description: Prometheus text format
|
|
content:
|
|
text/plain: {}
|
|
|
|
# --- Admin API (CRUD) ---
|
|
/v1/admin/tenants:
|
|
get:
|
|
tags: [Admin]
|
|
summary: List tenants
|
|
operationId: listTenants
|
|
responses:
|
|
"200": { description: List of tenants }
|
|
post:
|
|
tags: [Admin]
|
|
summary: Create tenant
|
|
operationId: createTenant
|
|
requestBody:
|
|
{ content: { "application/json": { schema: { $ref: "#/components/schemas/Tenant" } } } }
|
|
responses:
|
|
"201": { description: Created }
|
|
"400": { description: Validation error }
|
|
|
|
/v1/admin/tenants/{tenantId}:
|
|
get:
|
|
tags: [Admin]
|
|
summary: Get tenant
|
|
operationId: getTenant
|
|
parameters: [{ name: tenantId, in: path, required: true, schema: { type: string } }]
|
|
responses:
|
|
"200": { description: Tenant }
|
|
"404": { description: Not found }
|
|
put:
|
|
tags: [Admin]
|
|
summary: Update tenant
|
|
operationId: updateTenant
|
|
parameters: [{ name: tenantId, in: path, required: true, schema: { type: string } }]
|
|
requestBody:
|
|
{ content: { "application/json": { schema: { $ref: "#/components/schemas/Tenant" } } } }
|
|
responses:
|
|
"200": { description: Updated }
|
|
"404": { description: Not found }
|
|
delete:
|
|
tags: [Admin]
|
|
summary: Delete tenant
|
|
operationId: deleteTenant
|
|
parameters: [{ name: tenantId, in: path, required: true, schema: { type: string } }]
|
|
responses:
|
|
"204": { description: Deleted }
|
|
"404": { description: Not found }
|
|
|
|
/v1/admin/participants:
|
|
get:
|
|
tags: [Admin]
|
|
summary: List participants
|
|
parameters:
|
|
- name: tenantId
|
|
in: query
|
|
schema: { type: string }
|
|
responses:
|
|
"200": { description: List of participants }
|
|
post:
|
|
tags: [Admin]
|
|
summary: Create participant
|
|
operationId: createParticipant
|
|
requestBody:
|
|
{
|
|
content: { "application/json": { schema: { $ref: "#/components/schemas/Participant" } } },
|
|
}
|
|
responses:
|
|
"201": { description: Created }
|
|
"400": { description: Validation error }
|
|
|
|
/v1/admin/participants/{participantId}:
|
|
get:
|
|
tags: [Admin]
|
|
summary: Get participant
|
|
operationId: getParticipant
|
|
parameters: [{ name: participantId, in: path, required: true, schema: { type: string } }]
|
|
responses:
|
|
"200": { description: Participant }
|
|
"404": { description: Not found }
|
|
put:
|
|
tags: [Admin]
|
|
summary: Update participant
|
|
operationId: updateParticipant
|
|
parameters: [{ name: participantId, in: path, required: true, schema: { type: string } }]
|
|
requestBody:
|
|
{
|
|
content: { "application/json": { schema: { $ref: "#/components/schemas/Participant" } } },
|
|
}
|
|
responses:
|
|
"200": { description: Updated }
|
|
"404": { description: Not found }
|
|
delete:
|
|
tags: [Admin]
|
|
summary: Delete participant
|
|
operationId: deleteParticipant
|
|
parameters: [{ name: participantId, in: path, required: true, schema: { type: string } }]
|
|
responses:
|
|
"204": { description: Deleted }
|
|
"404": { description: Not found }
|
|
|
|
/v1/admin/participants/{participantId}/identifiers:
|
|
get:
|
|
tags: [Admin]
|
|
summary: List identifiers for participant
|
|
parameters: [{ name: participantId, in: path, required: true, schema: { type: string } }]
|
|
responses:
|
|
"200": { description: List of identifiers }
|
|
post:
|
|
tags: [Admin]
|
|
summary: Add identifier
|
|
operationId: createIdentifier
|
|
parameters: [{ name: participantId, in: path, required: true, schema: { type: string } }]
|
|
requestBody:
|
|
{ content: { "application/json": { schema: { $ref: "#/components/schemas/Identifier" } } } }
|
|
responses:
|
|
"201": { description: Created }
|
|
"400": { description: Validation error }
|
|
|
|
/v1/admin/participants/{participantId}/endpoints:
|
|
get:
|
|
tags: [Admin]
|
|
summary: List endpoints for participant
|
|
parameters: [{ name: participantId, in: path, required: true, schema: { type: string } }]
|
|
responses:
|
|
"200": { description: List of endpoints }
|
|
post:
|
|
tags: [Admin]
|
|
summary: Add endpoint
|
|
operationId: createEndpoint
|
|
parameters: [{ name: participantId, in: path, required: true, schema: { type: string } }]
|
|
requestBody:
|
|
{ content: { "application/json": { schema: { $ref: "#/components/schemas/Endpoint" } } } }
|
|
responses:
|
|
"201": { description: Created }
|
|
"400": { description: Validation error }
|
|
|
|
/v1/admin/participants/{participantId}/credentials:
|
|
get:
|
|
tags: [Admin]
|
|
summary: List credential refs for participant
|
|
parameters: [{ name: participantId, in: path, required: true, schema: { type: string } }]
|
|
responses:
|
|
"200": { description: List of credential refs }
|
|
post:
|
|
tags: [Admin]
|
|
summary: Add credential reference
|
|
operationId: createCredential
|
|
parameters: [{ name: participantId, in: path, required: true, schema: { type: string } }]
|
|
requestBody:
|
|
{
|
|
content:
|
|
{ "application/json": { schema: { $ref: "#/components/schemas/CredentialRef" } } },
|
|
}
|
|
responses:
|
|
"201": { description: Created }
|
|
"400": { description: Validation error }
|
|
|
|
/v1/admin/policies:
|
|
get:
|
|
tags: [Admin]
|
|
summary: List policies
|
|
parameters:
|
|
- name: tenantId
|
|
in: query
|
|
schema: { type: string }
|
|
responses:
|
|
"200": { description: List of policies }
|
|
post:
|
|
tags: [Admin]
|
|
summary: Create policy
|
|
operationId: createPolicy
|
|
requestBody:
|
|
{ content: { "application/json": { schema: { $ref: "#/components/schemas/Policy" } } } }
|
|
responses:
|
|
"201": { description: Created }
|
|
"400": { description: Validation error }
|
|
|
|
/v1/admin/policies/{policyId}:
|
|
get:
|
|
tags: [Admin]
|
|
summary: Get policy
|
|
parameters: [{ name: policyId, in: path, required: true, schema: { type: string } }]
|
|
responses:
|
|
"200": { description: Policy }
|
|
"404": { description: Not found }
|
|
put:
|
|
tags: [Admin]
|
|
summary: Update policy
|
|
operationId: updatePolicy
|
|
parameters: [{ name: policyId, in: path, required: true, schema: { type: string } }]
|
|
requestBody:
|
|
{ content: { "application/json": { schema: { $ref: "#/components/schemas/Policy" } } } }
|
|
responses:
|
|
"200": { description: Updated }
|
|
"404": { description: Not found }
|
|
delete:
|
|
tags: [Admin]
|
|
summary: Delete policy
|
|
operationId: deletePolicy
|
|
parameters: [{ name: policyId, in: path, required: true, schema: { type: string } }]
|
|
responses:
|
|
"204": { description: Deleted }
|
|
"404": { description: Not found }
|
|
|
|
components:
|
|
schemas:
|
|
# --- Resolver request/response (aligned with data-model and resolution-algorithm) ---
|
|
ResolveRequest:
|
|
type: object
|
|
required: [identifiers]
|
|
properties:
|
|
identifiers:
|
|
type: array
|
|
minItems: 1
|
|
items: { $ref: "#/components/schemas/IdentifierInput" }
|
|
serviceContext:
|
|
$ref: "#/components/schemas/ServiceContext"
|
|
constraints:
|
|
$ref: "#/components/schemas/ResolveConstraints"
|
|
tenant: { type: string, description: "Tenant scope for resolution" }
|
|
desiredProtocols:
|
|
type: array
|
|
items: { type: string }
|
|
description: "Preferred protocol domains (e.g. as4, ss7, peppol)"
|
|
|
|
IdentifierInput:
|
|
type: object
|
|
required: [type, value]
|
|
properties:
|
|
type:
|
|
{
|
|
type: string,
|
|
description: "Identifier type (e.g. as4.partyId, e164, peppol.participantId)",
|
|
}
|
|
value: { type: string }
|
|
scope: { type: string }
|
|
|
|
ServiceContext:
|
|
type: object
|
|
description: |
|
|
For ISO 20022 FI-to-FI (profile as4.fifi.iso20022.v1), service = `iso20022.fi` and action is one of
|
|
credit.transfer, fi.credit.transfer, payment.status, payment.cancellation, resolution.of.investigation, statement, notification.
|
|
properties:
|
|
service: { type: string }
|
|
action: { type: string }
|
|
process: { type: string }
|
|
documentType: { type: string }
|
|
|
|
ResolveConstraints:
|
|
type: object
|
|
properties:
|
|
trustDomain: { type: string }
|
|
region: { type: string }
|
|
jurisdiction: { type: string }
|
|
maxResults: { type: integer, minimum: 1 }
|
|
networkBrand:
|
|
type: string
|
|
description: "Card network (visa, mastercard, amex, discover, diners)"
|
|
tenantContract: { type: string, description: "Tenant contract for routing" }
|
|
connectivityGroup: { type: string }
|
|
requiredCapability: { type: string }
|
|
messageType: { type: string, description: "e.g. ISO8583 MTI or AS4 service/action" }
|
|
|
|
ResolveResponse:
|
|
type: object
|
|
required: [directives]
|
|
properties:
|
|
primary: { $ref: "#/components/schemas/RouteDirective" }
|
|
alternates:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/DirectiveWithReason" }
|
|
directives:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/RouteDirective" }
|
|
ttl: { type: integer, description: "Cache TTL in seconds" }
|
|
traceId: { type: string, format: uuid }
|
|
correlationId: { type: string }
|
|
failure_policy: { $ref: "#/components/schemas/FailurePolicy" }
|
|
negative_cache_ttl: { type: integer, description: "TTL for negative cache when no match" }
|
|
resolution_trace:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/ResolutionTraceEntry" }
|
|
|
|
DirectiveWithReason:
|
|
type: object
|
|
required: [directive]
|
|
properties:
|
|
directive: { $ref: "#/components/schemas/RouteDirective" }
|
|
reason: { type: string }
|
|
FailurePolicy:
|
|
type: object
|
|
properties:
|
|
retry: { type: boolean }
|
|
backoff: { type: string }
|
|
circuitBreak: { type: boolean }
|
|
ResolutionTraceEntry:
|
|
type: object
|
|
properties:
|
|
source: { type: string }
|
|
directiveIndex: { type: integer }
|
|
message: { type: string }
|
|
|
|
RouteDirective:
|
|
description: "Normalized routing output; see architecture/route-directive.md and route-directive.schema.json"
|
|
type: object
|
|
required: [target_protocol, target_address]
|
|
properties:
|
|
target_protocol: { type: string }
|
|
target_address: { type: string }
|
|
transport_profile: { type: string }
|
|
security:
|
|
type: object
|
|
properties:
|
|
signRequired: { type: boolean }
|
|
encryptRequired: { type: boolean }
|
|
keyRefs: { type: array, items: { type: string } }
|
|
algorithms: { type: object }
|
|
service_context:
|
|
type: object
|
|
properties:
|
|
service: { type: string }
|
|
action: { type: string }
|
|
serviceIndicator: { type: string }
|
|
qos:
|
|
type: object
|
|
properties:
|
|
retries: { type: integer }
|
|
receiptsRequired: { type: boolean }
|
|
ordering: { type: string }
|
|
ttl_seconds: { type: integer }
|
|
evidence:
|
|
oneOf:
|
|
- type: object
|
|
properties:
|
|
source: { type: string }
|
|
lastVerified: { type: string, format: date-time }
|
|
confidenceScore: { type: number }
|
|
signature: { type: string }
|
|
- type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
source: { type: string }
|
|
freshness: { type: string, format: date-time }
|
|
confidence: { type: number }
|
|
signature: { type: string }
|
|
|
|
# --- Admin entities (aligned with data-model) ---
|
|
Tenant:
|
|
type: object
|
|
properties:
|
|
id: { type: string }
|
|
name: { type: string }
|
|
createdAt: { type: string, format: date-time }
|
|
updatedAt: { type: string, format: date-time }
|
|
|
|
Participant:
|
|
type: object
|
|
properties:
|
|
id: { type: string }
|
|
tenantId: { type: string }
|
|
name: { type: string }
|
|
createdAt: { type: string, format: date-time }
|
|
updatedAt: { type: string, format: date-time }
|
|
|
|
Identifier:
|
|
type: object
|
|
properties:
|
|
id: { type: string }
|
|
participantId: { type: string }
|
|
identifier_type: { type: string }
|
|
value: { type: string }
|
|
scope: { type: string }
|
|
priority: { type: integer }
|
|
verified_at: { type: string, format: date-time }
|
|
|
|
Endpoint:
|
|
type: object
|
|
properties:
|
|
id: { type: string }
|
|
participantId: { type: string }
|
|
protocol: { type: string }
|
|
address: { type: string }
|
|
profile: { type: string }
|
|
priority: { type: integer }
|
|
status: { type: string, enum: [active, inactive, draining] }
|
|
|
|
CredentialRef:
|
|
type: object
|
|
properties:
|
|
id: { type: string }
|
|
participantId: { type: string }
|
|
credential_type: { type: string, enum: [tls, sign, encrypt] }
|
|
vault_ref: { type: string }
|
|
fingerprint: { type: string }
|
|
valid_from: { type: string, format: date-time }
|
|
valid_to: { type: string, format: date-time }
|
|
|
|
Policy:
|
|
type: object
|
|
properties:
|
|
id: { type: string }
|
|
tenantId: { type: string }
|
|
rule_json: { type: object, description: "ABAC rule" }
|
|
effect: { type: string, enum: [allow, deny] }
|
|
priority: { type: integer }
|