Skip to content

Commit 2a26c62

Browse files
committed
add sketch of OpenAPI spec
1 parent 94a16bf commit 2a26c62

File tree

4 files changed

+277
-1
lines changed

4 files changed

+277
-1
lines changed

daml/splice-api-credential-registry-v1/daml/Splice/Api/Credential/RegistryV1.daml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@ data Credential = Credential with
2828
-- Implementations SHOULD ensure that claims are stored in canonical form without
2929
-- redundant '#holder' suffixes in keys.
3030
--
31-
-- Keys SHOULD be namespaced in the form `dns.name/key` to avoid
31+
-- Keys MUST only contain characters from [a-zA-Z0-9._:-]
32+
-- and SHOULD be namespaced in the form `dns.name/key` to avoid
3233
-- collisions between different usecases.
3334

35+
3436
validFrom : Optional Time
3537
-- ^ The time from which this credential is valid.
3638
validUntil : Optional Time
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
2+
### Implementation note
3+
4+
We expect Scan to maintain the following indices.
5+
We expect Scan to use them in the following priority order:
6+
7+
```
8+
-- Used when holder is specified.
9+
create index idx_credentialrecord_holder ON CredentialRecord(holder, property, issuer, record_time);
10+
11+
-- Used when a property prefix is specified.
12+
create index idx_credentialrecord_issuer ON CredentialRecord(property, issuer, record_time);
13+
14+
-- Used when issuer is specified.
15+
create index idx_credentialrecord_issuer ON CredentialRecord(issuer, record_time);
16+
17+
-- Used when no filters are specified.
18+
create index idx_credentialrecord_recordtime ON CredentialRecord(record_time);
19+
```
20+
21+
The queries are constructed such that pagination follows the index order.
22+
They use a deterministic paging order based on the index columns, where `record_time` and
23+
`contract_id` are used as tie breakers.
24+
An ascending order for record_time is chosen to implement first write wins
25+
semantics, which is preferred as it incentivizes archiving older records.
26+
27+
The fallback order can be used to page through all records in the order in which
28+
they were created; and it can also be used to tail the table to ingest all records as
29+
they are created.
30+
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
# Copyright (c) 2025 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
openapi: 3.0.0
5+
info:
6+
title: credential registry off-ledger API
7+
description: |
8+
Implemented by credential registries for the purpose of creating, updating,
9+
and querying credential records.
10+
version: 1.0.0
11+
paths:
12+
13+
# TODO: fix the schema validation errors. The current state is meant as a sketch to align on the design.
14+
15+
# TODO: add info endpoint where one can learn about limits of the registry etc.
16+
17+
# TODO: consider renaming "CredentialRegistry" to "CredentialFactory" to be consistent with the token standard APIs; and to make the call below less confusing
18+
/registry/credentials/v1/credential-registry
19+
post:
20+
operationId: "getCredentialRegistry"
21+
description: |
22+
Get the credential registry contract and the choice context for updating records.
23+
requestBody:
24+
required: true
25+
content:
26+
application/json:
27+
schema:
28+
$ref: "#/components/schemas/GetCredentialRegistryRequest"
29+
responses:
30+
"200":
31+
description: ok
32+
content:
33+
application/json:
34+
schema:
35+
$ref: "#/components/schemas/CredentialsRegistryWithChoiceContext"
36+
"400":
37+
$ref: "#/components/responses/400"
38+
"404":
39+
$ref: "#/components/responses/404"
40+
41+
42+
/registry/credentials/v1/credentials
43+
get:
44+
operationId: "listCredentials"
45+
description: |
46+
List the credential records matching the provided filters.
47+
48+
Note that registries MAY decide to limit the number of records returned.
49+
50+
Decentralized registries MAY also store a record_time cutoff in the page token to make the
51+
responses more stable from a pagination perspective.
52+
parameters:
53+
- in: query
54+
name: holder
55+
schema:
56+
type: string
57+
required: false
58+
description: |
59+
The party that holds the credential records.
60+
- in: query
61+
name: issuer
62+
schema:
63+
type: string
64+
required: false
65+
description: |
66+
The party that issued the credential records.
67+
- in: query
68+
name: keyPrefix
69+
schema:
70+
type: string
71+
required: false
72+
description: |
73+
The prefix of the keys of the credential records.
74+
- in: query
75+
name: limit
76+
schema:
77+
type: integer
78+
format: int32
79+
required: false
80+
description: |
81+
The maximum number of credential records to return.
82+
- in: query
83+
name: pageToken
84+
schema:
85+
type: string
86+
required: false
87+
description: |
88+
The token for the page to retrieve.
89+
- in: query
90+
name: validAsOf
91+
schema:
92+
type: string
93+
format: date-time
94+
required: false
95+
description: |
96+
If provided, only return credential records that are valid at the given time.
97+
98+
TODO: consider whether we can use a `validAsOf` date that is
99+
slightly in the past to implement stable pagination for
100+
decentralized registries.
101+
102+
- in: query
103+
name: includeDisclosedContracts
104+
schema:
105+
type: boolean
106+
default: false
107+
required: false
108+
description: |
109+
If set to true, the response will include the disclosed contracts of the credentials
110+
for use with explicit contract disclosure upon command submission.
111+
- in: query
112+
name: excludeDebugFields
113+
schema:
114+
type: boolean
115+
default: false
116+
required: false
117+
description: |
118+
If set to true, then the disclosed contracts will not include debug fields.
119+
120+
responses:
121+
"200":
122+
description: ok
123+
content:
124+
application/json:
125+
schema:
126+
type: object
127+
properties:
128+
credentials:
129+
type: array
130+
items:
131+
$ref: "#/components/schemas/CredentialRecord"
132+
description: |
133+
The list of credential records matching the provided filters.
134+
nextPageToken:
135+
type: string
136+
description: |
137+
The token for the next page of results. Omitted if there are no more results.
138+
"400":
139+
$ref: "#/components/responses/400"
140+
"404":
141+
$ref: "#/components/responses/404"
142+
143+
144+
145+
components:
146+
responses:
147+
"400":
148+
description: "bad request"
149+
content:
150+
application/json:
151+
schema:
152+
$ref: "#/components/schemas/ErrorResponse"
153+
"404":
154+
description: "not found"
155+
content:
156+
application/json:
157+
schema:
158+
$ref: "#/components/schemas/ErrorResponse"
159+
160+
schemas:
161+
GetCredentialRegistryRequest:
162+
# TODO: fill out
163+
164+
CredentialRecord:
165+
type: object
166+
properties:
167+
credentialRecordView:
168+
type: object
169+
description: |
170+
The view computed for the credential record with the schema of Splice.Api.Credential.RegistryV1.CredentialRecordView.
171+
disclosedContract:
172+
$ref: "#/components/schemas/DisclosedContract"
173+
description: |
174+
The disclosed contract information for verifying the credential record using explicit contract disclosure.
175+
required:
176+
[
177+
"credentialRecordView",
178+
]
179+
180+
# Note: intentionally not shared with the other APIs to keep the self-contained, and because not all OpenAPI codegens support such shared definitions.
181+
DisclosedContract:
182+
type: object
183+
properties:
184+
templateId:
185+
type: string
186+
contractId:
187+
type: string
188+
createdEventBlob:
189+
type: string
190+
synchronizerId:
191+
description: |
192+
The synchronizer to which the contract is currently assigned.
193+
If the contract is in the process of being reassigned, then a "409" response is returned.
194+
type: string
195+
debugPackageName:
196+
description: |
197+
The name of the Daml package that was used to create the contract.
198+
Use this data only if you trust the provider, as it might not match the data in the
199+
`createdEventBlob`.
200+
type: string
201+
debugPayload:
202+
description: |
203+
The contract arguments that were used to create the contract.
204+
Use this data only if you trust the provider, as it might not match the data in the
205+
`createdEventBlob`.
206+
type: object
207+
debugCreatedAt:
208+
description: |
209+
The ledger effective time at which the contract was created.
210+
Use this data only if you trust the provider, as it might not match the data in the
211+
`disclosedContract`.
212+
type: string
213+
format: date-time
214+
required:
215+
[
216+
"templateId",
217+
"contractId",
218+
"createdEventBlob",
219+
"synchronizerId"
220+
]
221+
222+
ErrorResponse:
223+
type: object
224+
required:
225+
- error
226+
properties:
227+
error:
228+
type: string
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Copyright (c) 2025 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
# Description: Docker compose file for running Swagger UI with the transfer-instruction OpenAPI specification.
5+
# Usage: docker-compose up
6+
version: '3.7'
7+
8+
services:
9+
swagger-ui:
10+
image: swaggerapi/swagger-ui
11+
ports:
12+
- "8080:8080"
13+
environment:
14+
SWAGGER_JSON: /spec/credential-registry.yaml
15+
volumes:
16+
- ./credential-registry.yaml:/spec/credential-registry.yaml

0 commit comments

Comments
 (0)