Initial commit: AS4/411 directory and discovery service for Sankofa Marketplace
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
0
docs/api/.gitkeep
Normal file
0
docs/api/.gitkeep
Normal file
18
docs/api/README.md
Normal file
18
docs/api/README.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# API definitions
|
||||
|
||||
- **OpenAPI:** [openapi.yaml](openapi.yaml) — REST API for resolve, bulk-resolve, admin, system.
|
||||
- **Route directive schema:** [route-directive.schema.json](route-directive.schema.json) — JSON Schema for RouteDirective and ResolveResponse.
|
||||
- **Protobuf:** [proto/resolver.proto](proto/resolver.proto) — Resolver service and messages (ResolveRequest, ResolveResponse, RouteDirective). Package `as411.resolver.v1`.
|
||||
|
||||
## Generating stubs from Proto
|
||||
|
||||
From the repo root, with `protoc` installed:
|
||||
|
||||
```bash
|
||||
# Example (adjust paths for your language)
|
||||
protoc -I docs/api/proto docs/api/proto/resolver.proto --go_out=paths=source_relative:.
|
||||
# Or with buf (if using buf.gen.yaml):
|
||||
# buf generate docs/api/proto
|
||||
```
|
||||
|
||||
gRPC server implementation is optional; the Proto file defines the contract for clients and future gRPC support.
|
||||
530
docs/api/openapi.yaml
Normal file
530
docs/api/openapi.yaml
Normal file
@@ -0,0 +1,530 @@
|
||||
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 }
|
||||
120
docs/api/proto/resolver.proto
Normal file
120
docs/api/proto/resolver.proto
Normal file
@@ -0,0 +1,120 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package as411.resolver.v1;
|
||||
|
||||
option go_package = "github.com/as4-411/api/proto/resolver/v1;resolverv1";
|
||||
|
||||
// ResolverService provides resolution of identifiers to routing directives.
|
||||
// Aligned with REST /v1/resolve and /v1/bulk-resolve; see OpenAPI and route-directive.schema.json.
|
||||
service ResolverService {
|
||||
rpc Resolve(ResolveRequest) returns (ResolveResponse);
|
||||
rpc BulkResolve(BulkResolveRequest) returns (BulkResolveResponse);
|
||||
}
|
||||
|
||||
message ResolveRequest {
|
||||
repeated IdentifierInput identifiers = 1;
|
||||
ServiceContext service_context = 2;
|
||||
ResolveConstraints constraints = 3;
|
||||
string tenant = 4;
|
||||
repeated string desired_protocols = 5;
|
||||
}
|
||||
|
||||
message IdentifierInput {
|
||||
string type = 1; // e.g. as4.partyId, e164, peppol.participantId
|
||||
string value = 2;
|
||||
string scope = 3; // e.g. BIC, LEI
|
||||
}
|
||||
|
||||
message ServiceContext {
|
||||
string service = 1; // e.g. iso20022.fi
|
||||
string action = 2; // e.g. credit.transfer
|
||||
string process = 3;
|
||||
string document_type = 4;
|
||||
}
|
||||
|
||||
message ResolveConstraints {
|
||||
string trust_domain = 1;
|
||||
string region = 2;
|
||||
string jurisdiction = 3;
|
||||
int32 max_results = 4;
|
||||
string network_brand = 5;
|
||||
string tenant_contract = 6;
|
||||
string connectivity_group = 7;
|
||||
string required_capability = 8;
|
||||
string message_type = 9;
|
||||
}
|
||||
|
||||
message ResolveResponse {
|
||||
RouteDirective primary = 1;
|
||||
repeated DirectiveWithReason alternates = 2;
|
||||
repeated RouteDirective directives = 3;
|
||||
int32 ttl = 4;
|
||||
string trace_id = 5;
|
||||
string correlation_id = 6;
|
||||
FailurePolicy failure_policy = 7;
|
||||
int32 negative_cache_ttl = 8;
|
||||
repeated ResolutionTraceEntry resolution_trace = 9;
|
||||
}
|
||||
|
||||
message RouteDirective {
|
||||
string target_protocol = 1;
|
||||
string target_address = 2;
|
||||
string transport_profile = 3; // e.g. as4.fifi.iso20022.v1
|
||||
RouteDirectiveSecurity security = 4;
|
||||
RouteDirectiveServiceContext service_context = 5;
|
||||
RouteDirectiveQos qos = 6;
|
||||
int32 ttl_seconds = 7;
|
||||
repeated EvidenceItem evidence = 8;
|
||||
}
|
||||
|
||||
message EvidenceItem {
|
||||
string source = 1;
|
||||
string freshness = 2; // date-time
|
||||
double confidence = 3;
|
||||
string signature = 4;
|
||||
}
|
||||
|
||||
message RouteDirectiveSecurity {
|
||||
bool sign_required = 1;
|
||||
bool encrypt_required = 2;
|
||||
repeated string key_refs = 3;
|
||||
map<string, string> algorithms = 4;
|
||||
}
|
||||
|
||||
message RouteDirectiveServiceContext {
|
||||
string service = 1;
|
||||
string action = 2;
|
||||
string service_indicator = 3;
|
||||
}
|
||||
|
||||
message RouteDirectiveQos {
|
||||
int32 retries = 1;
|
||||
bool receipts_required = 2;
|
||||
string ordering = 3;
|
||||
}
|
||||
|
||||
message DirectiveWithReason {
|
||||
RouteDirective directive = 1;
|
||||
string reason = 2;
|
||||
}
|
||||
|
||||
message FailurePolicy {
|
||||
bool retry = 1;
|
||||
string backoff = 2;
|
||||
bool circuit_break = 3;
|
||||
}
|
||||
|
||||
message ResolutionTraceEntry {
|
||||
string source = 1;
|
||||
int32 directive_index = 2;
|
||||
string message = 3;
|
||||
}
|
||||
|
||||
message BulkResolveRequest {
|
||||
repeated ResolveRequest requests = 1;
|
||||
}
|
||||
|
||||
message BulkResolveResponse {
|
||||
repeated ResolveResponse results = 1;
|
||||
string trace_id = 2;
|
||||
}
|
||||
110
docs/api/route-directive.schema.json
Normal file
110
docs/api/route-directive.schema.json
Normal file
@@ -0,0 +1,110 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://as4-411.example/schemas/route-directive.json",
|
||||
"title": "RouteDirective and ResolveResponse",
|
||||
"description": "Formal schema for routing directive and resolve response. See docs/architecture/route-directive.md.",
|
||||
"definitions": {
|
||||
"RouteDirectiveSecurity": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"signRequired": { "type": "boolean" },
|
||||
"encryptRequired": { "type": "boolean" },
|
||||
"keyRefs": { "type": "array", "items": { "type": "string" } },
|
||||
"algorithms": { "type": "object" }
|
||||
}
|
||||
},
|
||||
"RouteDirectiveServiceContext": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"service": { "type": "string" },
|
||||
"action": { "type": "string" },
|
||||
"serviceIndicator": { "type": "string" }
|
||||
}
|
||||
},
|
||||
"RouteDirectiveQos": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"retries": { "type": "integer" },
|
||||
"receiptsRequired": { "type": "boolean" },
|
||||
"ordering": { "type": "string" }
|
||||
}
|
||||
},
|
||||
"EvidenceItem": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"source": { "type": "string" },
|
||||
"freshness": { "type": "string", "format": "date-time" },
|
||||
"confidence": { "type": "number" },
|
||||
"signature": { "type": "string" }
|
||||
}
|
||||
},
|
||||
"RouteDirective": {
|
||||
"type": "object",
|
||||
"required": ["target_protocol", "target_address"],
|
||||
"properties": {
|
||||
"target_protocol": { "type": "string" },
|
||||
"target_address": { "type": "string" },
|
||||
"transport_profile": { "type": "string" },
|
||||
"security": { "$ref": "#/definitions/RouteDirectiveSecurity" },
|
||||
"service_context": { "$ref": "#/definitions/RouteDirectiveServiceContext" },
|
||||
"qos": { "$ref": "#/definitions/RouteDirectiveQos" },
|
||||
"ttl_seconds": { "type": "integer" },
|
||||
"evidence": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/definitions/EvidenceItem" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"DirectiveWithReason": {
|
||||
"type": "object",
|
||||
"required": ["directive"],
|
||||
"properties": {
|
||||
"directive": { "$ref": "#/definitions/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" }
|
||||
}
|
||||
},
|
||||
"ResolveResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"primary": { "$ref": "#/definitions/RouteDirective" },
|
||||
"alternates": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/definitions/DirectiveWithReason" }
|
||||
},
|
||||
"directives": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/definitions/RouteDirective" }
|
||||
},
|
||||
"ttl": { "type": "integer" },
|
||||
"traceId": { "type": "string", "format": "uuid" },
|
||||
"correlationId": { "type": "string" },
|
||||
"failure_policy": { "$ref": "#/definitions/FailurePolicy" },
|
||||
"negative_cache_ttl": { "type": "integer" },
|
||||
"resolution_trace": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/definitions/ResolutionTraceEntry" }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"oneOf": [
|
||||
{ "$ref": "#/definitions/RouteDirective" },
|
||||
{ "$ref": "#/definitions/ResolveResponse" }
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user