@eudiplo/cli 8.1.0-main.a6a67b3 → 8.1.0-main.b98cc00

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +1 -1
  2. package/dist/commands/completion/action.js +1 -1
  3. package/dist/commands/completion/action.js.map +1 -1
  4. package/dist/commands/completion/index.d.ts.map +1 -1
  5. package/dist/commands/completion/index.js +6 -1
  6. package/dist/commands/completion/index.js.map +1 -1
  7. package/dist/commands/config/action.d.ts.map +1 -1
  8. package/dist/commands/config/action.js.map +1 -1
  9. package/dist/commands/config/portability/migrations.spec.js +5 -3
  10. package/dist/commands/config/portability/migrations.spec.js.map +1 -1
  11. package/dist/commands/config/validate/schemas.js.map +1 -1
  12. package/dist/commands/config/validate/validator.js +7 -4
  13. package/dist/commands/config/validate/validator.js.map +1 -1
  14. package/dist/commands/instance/action.d.ts.map +1 -1
  15. package/dist/commands/instance/action.js.map +1 -1
  16. package/dist/index.js +1716 -274
  17. package/dist/runtime.js +1 -1
  18. package/dist/runtime.js.map +1 -1
  19. package/dist/services/cli-config.d.ts.map +1 -1
  20. package/dist/services/cli-config.js +5 -2
  21. package/dist/services/cli-config.js.map +1 -1
  22. package/dist/services/compose-project.d.ts.map +1 -1
  23. package/dist/services/compose-project.js +12 -7
  24. package/dist/services/compose-project.js.map +1 -1
  25. package/dist/services/compose-upgrade.js +1 -1
  26. package/dist/services/compose-upgrade.js.map +1 -1
  27. package/dist/services/diagnostics.d.ts.map +1 -1
  28. package/dist/services/diagnostics.js +14 -9
  29. package/dist/services/diagnostics.js.map +1 -1
  30. package/dist/services/kubectl.d.ts.map +1 -1
  31. package/dist/services/kubectl.js +1 -6
  32. package/dist/services/kubectl.js.map +1 -1
  33. package/package.json +5 -3
  34. package/templates/demo-config/trust-lists/trustlist-580831bc-ef11-43f4-a3be-a2b6bf1b29a3-config.json +1 -97
  35. package/templates/docker-compose.yml +2 -2
  36. package/templates/schemas/IssuanceConfig.schema.json +13 -0
  37. package/templates/schemas/IssuanceConfigFile.schema.json +663 -1
  38. package/templates/schemas/PresentationConfigCreateDto.schema.json +3 -6
  39. package/templates/schemas/PresentationConfigFile.schema.json +723 -1
package/dist/index.js CHANGED
@@ -11388,12 +11388,7 @@ import { homedir } from "node:os";
11388
11388
 
11389
11389
  // src/services/kubectl.ts
11390
11390
  function scopeArgs(scope) {
11391
- return [
11392
- "--context",
11393
- scope.context,
11394
- "--namespace",
11395
- scope.namespace
11396
- ];
11391
+ return ["--context", scope.context, "--namespace", scope.namespace];
11397
11392
  }
11398
11393
  function resolveScope(instance, instanceName) {
11399
11394
  if (!instance.context) {
@@ -11922,7 +11917,12 @@ function powershellCompletion() {
11922
11917
  }
11923
11918
 
11924
11919
  // src/commands/completion/index.ts
11925
- var supportedShells = ["bash", "zsh", "fish", "powershell"];
11920
+ var supportedShells = [
11921
+ "bash",
11922
+ "zsh",
11923
+ "fish",
11924
+ "powershell"
11925
+ ];
11926
11926
  function createCompletionCommand(context, setExitCode) {
11927
11927
  return new Command("completion").description("Generate shell completion scripts").addArgument(
11928
11928
  new Argument("<shell>", "shell to generate completion for").choices(
@@ -11933,14 +11933,22 @@ function createCompletionCommand(context, setExitCode) {
11933
11933
  });
11934
11934
  }
11935
11935
  function createCompletionCandidatesCommand(context, setExitCode) {
11936
- return new Command("_complete").argument("[words...]").allowUnknownOption(true).action(async (words, _options, command) => {
11937
- if (!command.parent) {
11938
- throw new Error("Completion command is not attached to the CLI root.");
11936
+ return new Command("_complete").argument("[words...]").allowUnknownOption(true).action(
11937
+ async (words, _options, command) => {
11938
+ if (!command.parent) {
11939
+ throw new Error(
11940
+ "Completion command is not attached to the CLI root."
11941
+ );
11942
+ }
11943
+ setExitCode(
11944
+ await runCompletionCandidates(
11945
+ command.parent,
11946
+ words,
11947
+ context
11948
+ )
11949
+ );
11939
11950
  }
11940
- setExitCode(
11941
- await runCompletionCandidates(command.parent, words, context)
11942
- );
11943
- });
11951
+ );
11944
11952
  }
11945
11953
 
11946
11954
  // src/commands/commands/render.ts
@@ -12028,8 +12036,10 @@ function runConfigShow(configPath, config, json, context) {
12028
12036
  }
12029
12037
  context.stdout.write(`Config: ${configPath}
12030
12038
  `);
12031
- context.stdout.write(`Default instance: ${config.defaultInstance ?? "none"}
12032
- `);
12039
+ context.stdout.write(
12040
+ `Default instance: ${config.defaultInstance ?? "none"}
12041
+ `
12042
+ );
12033
12043
  const instances = Object.entries(config.instances).sort(
12034
12044
  ([left], [right]) => left.localeCompare(right)
12035
12045
  );
@@ -14887,7 +14897,7 @@ var CONFIG_FORMATS = {
14887
14897
  IssuanceConfig: {
14888
14898
  slug: "issuance-config",
14889
14899
  file: "IssuanceConfigFile",
14890
- version: 1
14900
+ version: 2
14891
14901
  },
14892
14902
  CredentialConfig: {
14893
14903
  slug: "credential-config",
@@ -14897,7 +14907,7 @@ var CONFIG_FORMATS = {
14897
14907
  PresentationConfig: {
14898
14908
  slug: "presentation-config",
14899
14909
  file: "PresentationConfigFile",
14900
- version: 1
14910
+ version: 2
14901
14911
  },
14902
14912
  AttributeProvider: {
14903
14913
  slug: "attribute-provider",
@@ -14936,7 +14946,42 @@ function resourceId(input) {
14936
14946
  throw new Error(`Configuration spec.${field} is required`);
14937
14947
  return id;
14938
14948
  }
14939
- var CONFIG_MIGRATIONS = [];
14949
+ var presentationConfigV1ToV2 = {
14950
+ id: "presentation-config-v2-provides-attestations",
14951
+ kind: "PresentationConfig",
14952
+ from: 1,
14953
+ to: 2,
14954
+ migrate(spec) {
14955
+ const registrationCert = spec.registration_cert;
14956
+ if (!object(registrationCert) || !object(registrationCert.body) || !("provided_attestations" in registrationCert.body)) {
14957
+ return { spec };
14958
+ }
14959
+ const { provided_attestations: _, ...body } = registrationCert.body;
14960
+ return {
14961
+ spec: { ...spec, registration_cert: { ...registrationCert, body } },
14962
+ issues: [
14963
+ {
14964
+ severity: "warning",
14965
+ code: "PROVIDED_ATTESTATIONS_REMOVED",
14966
+ path: "/spec/registration_cert/body/provided_attestations",
14967
+ message: "provided_attestations is not part of the registrar API and was removed. Set provides_attestations to the credential type identifiers (SD-JWT VC vct or mdoc doctype) the issuer provides."
14968
+ }
14969
+ ]
14970
+ };
14971
+ }
14972
+ };
14973
+ var CONFIG_MIGRATIONS = [
14974
+ {
14975
+ id: "issuance-config-v2-offer-lifetime",
14976
+ kind: "IssuanceConfig",
14977
+ from: 1,
14978
+ to: 2,
14979
+ // v2 only adds the optional offerLifetimeSeconds: a v1 spec is a
14980
+ // valid v2 spec whose offers keep having no lifetime.
14981
+ migrate: (spec) => ({ spec })
14982
+ },
14983
+ presentationConfigV1ToV2
14984
+ ];
14940
14985
  function schemaUrl(kind, version = CONFIG_FORMATS[kind].version) {
14941
14986
  if (!Number.isSafeInteger(version) || version < 1)
14942
14987
  throw new Error("Invalid config version");
@@ -20001,233 +20046,1627 @@ var CONFIG_SCHEMAS = [
20001
20046
  "title": "CreateWebhookEndpointDto"
20002
20047
  }
20003
20048
  }
20004
- }
20005
- ];
20006
-
20007
- // ../../packages/eudiplo-config-format/dist/config-validator.js
20008
- var ajv = new import__.Ajv2020({
20009
- allErrors: true,
20010
- strict: false,
20011
- validateFormats: false
20012
- });
20013
- for (const schema of CONFIG_SCHEMAS)
20014
- ajv.addSchema(schema);
20015
- function validateConfigDocument(document) {
20016
- const file = serializeDocument(document);
20017
- const validate = ajv.getSchema(file.$schema);
20018
- if (!validate)
20019
- throw new Error(`No bundled validator for ${file.$schema}`);
20020
- const issues = [];
20021
- if (!validate(file)) {
20022
- for (const issue of validate.errors ?? [])
20023
- issues.push({
20024
- severity: "error",
20025
- code: "CONFIG_SCHEMA_VALIDATION_FAILED",
20026
- path: issue.instancePath || "/",
20027
- message: issue.keyword === "additionalProperties" ? `Unknown property: ${String(issue.params.additionalProperty)}` : issue.message ?? "Invalid configuration",
20028
- resource: { kind: document.kind, id: resourceId(document) }
20029
- });
20030
- }
20031
- const id = document.kind === "Client" ? document.spec.clientId : document.spec.id;
20032
- if (id !== void 0 && id !== resourceId(document))
20033
- issues.push({
20034
- severity: "error",
20035
- code: "RESOURCE_ID_MISMATCH",
20036
- path: document.kind === "Client" ? "/spec/clientId" : "/spec/id",
20037
- message: "Resource identifier does not match metadata.id"
20038
- });
20039
- return issues;
20040
- }
20041
-
20042
- // src/commands/config/portability/migrations.ts
20043
- function upgradeDocument(input) {
20044
- const result = migrateDocument(input, validateConfigDocument);
20045
- return { ...result, document: serializeDocument(result.document) };
20046
- }
20047
-
20048
- // src/commands/config/portability/upgrade.ts
20049
- var codec = new ConfigBundleCodec();
20050
- function parse3(text, path2) {
20051
- try {
20052
- return JSON.parse(text);
20053
- } catch {
20054
- throw new Error(`Invalid JSON in ${path2}`);
20055
- }
20056
- }
20057
- function upgradeJson(input, file, context) {
20058
- const bundle = Array.isArray(input?.documents);
20059
- if (bundle) assertConfigBundle(input);
20060
- const results = (bundle ? input.documents : [input]).map(
20061
- (document) => upgradeDocument(document)
20062
- );
20063
- let blocked = false;
20064
- for (const result of results) {
20065
- for (const issue of result.issues) {
20066
- context.stderr.write(
20067
- `${file}${issue.path}: ${issue.severity} ${issue.code}: ${issue.message}
20068
- `
20069
- );
20070
- if (issue.severity !== "warning") blocked = true;
20071
- }
20072
- for (const migration of result.migrations)
20073
- context.stdout.write(`${file}: migration ${migration}
20074
- `);
20075
- }
20076
- if (blocked) throw new Error(`${file}: upgrade blocked; no output written`);
20077
- if (!bundle) return results[0].document;
20078
- const documents = results.map(
20079
- (result) => result.document
20080
- );
20081
- const resources = input.manifest.resources.map(
20082
- (resource) => {
20083
- const index = input.documents.findIndex(
20084
- (candidate) => normalizeDocument(candidate).kind === resource.kind && resourceId(candidate) === resource.id
20085
- );
20086
- const document = documents[index];
20087
- return {
20088
- ...resource,
20089
- id: resourceId(document),
20090
- $schema: document.$schema,
20091
- sha256: createHash2("sha256").update(JSON.stringify(document)).digest("hex")
20092
- };
20093
- }
20094
- );
20095
- const output = {
20096
- ...input,
20097
- manifest: { ...input.manifest, formatVersion: 2, resources },
20098
- documents
20099
- };
20100
- assertConfigBundle(output);
20101
- return output;
20102
- }
20103
- function report(input, output, file, parsed, context) {
20104
- const changed = stableConfigJson(input) !== stableConfigJson(output);
20105
- context.stdout.write(
20106
- `${file}: ${changed ? "upgrade required" : "current"}
20107
- `
20108
- );
20109
- if (parsed.flags.diff === true)
20110
- for (const change of configChanges(input, output)) {
20111
- context.stdout.write(
20112
- ` ${change.path}: ${JSON.stringify(change.before) ?? "(absent)"} -> ${JSON.stringify(change.after) ?? "(absent)"}
20113
- `
20114
- );
20115
- }
20116
- return changed;
20117
- }
20118
- function inferredKind(path2) {
20119
- const normalized = path2.split(sep2).join("/");
20120
- const match = TENANT_RESOURCE_REGISTRY.find(
20121
- (entry) => entry.kind === "file" ? normalized === entry.file || normalized.endsWith(`/${entry.file}`) : normalized.endsWith(`/${entry.subfolder}/${basename2(path2)}`) || normalized === `${entry.subfolder}/${basename2(path2)}`
20122
- );
20123
- return CONFIG_RESOURCE_KINDS.find(
20124
- (kind) => `${CONFIG_FORMATS[kind].file}.schema.json` === match?.schemaFile
20125
- );
20126
- }
20127
- function wrapBare(kind, input, path2) {
20128
- if (!input || typeof input !== "object" || Array.isArray(input))
20129
- throw new Error(`${path2}: configuration must be an object`);
20130
- const singleton = {
20131
- Tenant: "tenant",
20132
- KmsConfig: "kms",
20133
- RegistrarConfig: "registrar",
20134
- IssuanceConfig: "issuance"
20135
- };
20136
- const spec = structuredClone(input);
20137
- if (kind === "KeyChain" && spec.key && !spec.keySource) {
20138
- spec.keySource = { type: "private-jwk", jwk: spec.key };
20139
- delete spec.key;
20140
- }
20141
- const id = String(
20142
- singleton[kind] ?? spec.id ?? spec.clientId ?? basename2(path2, ".json")
20143
- );
20144
- if (!singleton[kind]) spec[kind === "Client" ? "clientId" : "id"] = id;
20145
- return { $schema: schemaUrl(kind, 1), metadata: { generation: 1 }, spec };
20146
- }
20147
- async function folderFiles(path2) {
20148
- const files = [];
20149
- for (const entry of await readdir(path2, { withFileTypes: true })) {
20150
- if (entry.name.startsWith(".")) continue;
20151
- const file = join4(path2, entry.name);
20152
- if (entry.isSymbolicLink())
20153
- throw new Error(`Config folder contains a symbolic link: ${file}`);
20154
- if (entry.isDirectory()) files.push(...await folderFiles(file));
20155
- else if (entry.isFile()) files.push(file);
20156
- }
20157
- return files.sort();
20158
- }
20159
- async function upgradeFolder(source, parsed, context) {
20160
- const outputs = /* @__PURE__ */ new Map();
20161
- let changed = 0;
20162
- for (const file of await folderFiles(source)) {
20163
- if (extname(file) !== ".json" || relative2(source, file).split(sep2).includes("images"))
20164
- continue;
20165
- const input = parse3(await readFile4(file, "utf8"), file);
20166
- const kind = inferredKind(relative2(source, file));
20167
- if (!kind && !isConfigDocument(input)) continue;
20168
- const candidate = isConfigDocument(input) ? input : wrapBare(kind, input, file);
20169
- const output = upgradeJson(candidate, file, context);
20170
- if (kind && normalizeDocument(output).kind !== kind)
20171
- throw new Error(`${file}: expected ${kind} configuration`);
20172
- if (report(input, output, relative2(source, file), parsed, context))
20173
- changed++;
20174
- outputs.set(
20175
- relative2(source, file),
20176
- `${JSON.stringify(output, null, 2)}
20177
- `
20178
- );
20179
- }
20180
- if (!outputs.size)
20181
- throw new Error(`No configuration documents found in ${source}`);
20182
- context.stdout.write(
20183
- `${outputs.size - changed} current, ${changed} require upgrading
20184
- `
20185
- );
20186
- if (parsed.flags.check === true) return changed ? 1 : 0;
20187
- if (parsed.flags["dry-run"] === true) return 0;
20188
- const destination = resolve3(
20189
- context.cwd,
20190
- readStringFlag(parsed.flags, "output") ?? `${source}.upgraded`
20191
- );
20192
- const overlap = (parent, child) => {
20193
- const path2 = relative2(parent, child);
20194
- return path2 === "" || !path2.startsWith(`..${sep2}`) && path2 !== "..";
20195
- };
20196
- if (overlap(source, destination) || overlap(destination, source))
20197
- throw new Error(
20198
- "Folder output must be separate from the source directory"
20199
- );
20200
- await lstat(destination).then(
20201
- () => {
20202
- throw new Error(`Output already exists: ${destination}`);
20203
- },
20204
- (error) => {
20205
- if (error.code !== "ENOENT") throw error;
20206
- }
20207
- );
20208
- await mkdir3(dirname3(destination), { recursive: true });
20209
- const staging = await mkdtemp(
20210
- join4(dirname3(destination), ".eudiplo-upgrade-")
20211
- );
20212
- try {
20213
- await cp(source, staging, {
20214
- recursive: true,
20215
- filter: (path2) => path2 === source || !relative2(source, path2).split(sep2).some((part) => part.startsWith("."))
20216
- });
20217
- for (const [path2, contents] of outputs)
20218
- await atomicWriteFile(join4(staging, path2), contents);
20219
- await rename2(staging, destination);
20220
- context.stdout.write(
20221
- `Wrote upgraded configuration folder to ${destination}
20222
- `
20223
- );
20224
- } finally {
20225
- await rm(staging, { recursive: true, force: true });
20226
- }
20227
- return 0;
20228
- }
20229
- async function upgradeFile(parsed, context) {
20230
- const name = parsed.positionals[0];
20049
+ },
20050
+ {
20051
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
20052
+ "$id": "https://eudiplo.dev/schemas/v2/IssuanceConfigFile.schema.json",
20053
+ "title": "IssuanceConfigFile",
20054
+ "type": "object",
20055
+ "properties": {
20056
+ "$schema": {
20057
+ "type": "string",
20058
+ "const": "https://eudiplo.dev/schemas/v2/IssuanceConfigFile.schema.json"
20059
+ },
20060
+ "metadata": {
20061
+ "type": "object",
20062
+ "properties": {
20063
+ "generation": {
20064
+ "type": "integer",
20065
+ "minimum": 1,
20066
+ "description": "Monotonically increasing configuration generation."
20067
+ },
20068
+ "ownership": {
20069
+ "type": "string",
20070
+ "enum": [
20071
+ "unmanaged",
20072
+ "file-managed"
20073
+ ],
20074
+ "description": "Requested ownership recorded when the document is applied."
20075
+ }
20076
+ },
20077
+ "additionalProperties": false
20078
+ },
20079
+ "spec": {
20080
+ "$ref": "#/$defs/IssuanceConfig"
20081
+ }
20082
+ },
20083
+ "required": [
20084
+ "$schema",
20085
+ "spec"
20086
+ ],
20087
+ "additionalProperties": false,
20088
+ "$defs": {
20089
+ "IssuanceConfig": {
20090
+ "type": "object",
20091
+ "properties": {
20092
+ "batchSize": {
20093
+ "description": "Optional issuance batch size.",
20094
+ "type": "integer",
20095
+ "minimum": 1,
20096
+ "maximum": 9007199254740991
20097
+ },
20098
+ "dPopRequired": {
20099
+ "description": "Require DPoP proofs for issuance endpoints.",
20100
+ "type": "boolean"
20101
+ },
20102
+ "walletAttestationRequired": {
20103
+ "description": "Default wallet attestation requirement for managed authorization servers.",
20104
+ "type": "boolean"
20105
+ },
20106
+ "walletProviderTrustLists": {
20107
+ "description": "Shared wallet provider trust lists for key attestations and default authorization server wallet authentication.",
20108
+ "type": "array",
20109
+ "items": {
20110
+ "type": "object",
20111
+ "properties": {
20112
+ "trustListId": {
20113
+ "type": "string",
20114
+ "minLength": 1
20115
+ },
20116
+ "url": {
20117
+ "description": "URL of the wallet provider trust list.",
20118
+ "type": "string",
20119
+ "format": "uri"
20120
+ },
20121
+ "verifierKey": {
20122
+ "description": "Optional verifier key material used for trust list verification.",
20123
+ "type": "object",
20124
+ "propertyNames": {
20125
+ "type": "string"
20126
+ },
20127
+ "additionalProperties": {}
20128
+ },
20129
+ "verifierX509Der": {
20130
+ "description": "Optional verifier certificate in DER/base64 form.",
20131
+ "type": "string"
20132
+ }
20133
+ },
20134
+ "additionalProperties": false
20135
+ }
20136
+ },
20137
+ "signingKeyId": {
20138
+ "description": "Default signing key chain id for credential issuance.",
20139
+ "type": "string",
20140
+ "minLength": 1
20141
+ },
20142
+ "authorizationServers": {
20143
+ "minItems": 1,
20144
+ "type": "array",
20145
+ "items": {
20146
+ "oneOf": [
20147
+ {
20148
+ "type": "object",
20149
+ "properties": {
20150
+ "type": {
20151
+ "type": "string",
20152
+ "const": "external",
20153
+ "description": "Use an externally managed authorization server."
20154
+ },
20155
+ "id": {
20156
+ "type": "string",
20157
+ "minLength": 1,
20158
+ "description": "Authorization server identifier."
20159
+ },
20160
+ "issuer": {
20161
+ "type": "string",
20162
+ "format": "uri",
20163
+ "description": "Issuer URL for the external authorization server."
20164
+ },
20165
+ "sessionBinding": {
20166
+ "description": "Explicit mapping from an external access-token claim to an existing issuance session.",
20167
+ "type": "object",
20168
+ "properties": {
20169
+ "method": {
20170
+ "type": "string",
20171
+ "const": "access_token_claim",
20172
+ "description": "Read the correlation value from a configured access-token claim."
20173
+ },
20174
+ "claim": {
20175
+ "type": "string",
20176
+ "minLength": 1,
20177
+ "description": "Claim name that contains the issuance-session correlation value."
20178
+ }
20179
+ },
20180
+ "required": [
20181
+ "method",
20182
+ "claim"
20183
+ ],
20184
+ "additionalProperties": false
20185
+ },
20186
+ "label": {
20187
+ "description": "Optional display label for UI selection.",
20188
+ "type": "string"
20189
+ },
20190
+ "enabled": {
20191
+ "description": "Whether this authorization server entry is enabled.",
20192
+ "type": "boolean"
20193
+ }
20194
+ },
20195
+ "required": [
20196
+ "type",
20197
+ "id",
20198
+ "issuer"
20199
+ ],
20200
+ "additionalProperties": false
20201
+ },
20202
+ {
20203
+ "type": "object",
20204
+ "properties": {
20205
+ "type": {
20206
+ "type": "string",
20207
+ "const": "oid4vp",
20208
+ "description": "Use OID4VP-based authorization server chaining."
20209
+ },
20210
+ "id": {
20211
+ "type": "string",
20212
+ "minLength": 1,
20213
+ "description": "Authorization server identifier."
20214
+ },
20215
+ "presentationConfigId": {
20216
+ "type": "string",
20217
+ "minLength": 1,
20218
+ "description": "Presentation configuration id used during authorization."
20219
+ },
20220
+ "immediateWalletRedirect": {
20221
+ "description": "Redirect wallets immediately after authorization response creation.",
20222
+ "type": "boolean"
20223
+ },
20224
+ "token": {
20225
+ "description": "Optional token issuance settings.",
20226
+ "type": "object",
20227
+ "properties": {
20228
+ "lifetimeSeconds": {
20229
+ "description": "Access token lifetime in seconds.",
20230
+ "type": "number",
20231
+ "minimum": 60
20232
+ },
20233
+ "signingKeyId": {
20234
+ "description": "Optional key chain id used to sign issued tokens.",
20235
+ "type": "string",
20236
+ "minLength": 1
20237
+ },
20238
+ "refreshTokenEnabled": {
20239
+ "description": "Enable issuing refresh tokens.",
20240
+ "type": "boolean"
20241
+ },
20242
+ "refreshTokenExpiresInSeconds": {
20243
+ "description": "Refresh token lifetime in seconds.",
20244
+ "type": "number",
20245
+ "minimum": 60
20246
+ }
20247
+ },
20248
+ "additionalProperties": false
20249
+ },
20250
+ "requireDPoP": {
20251
+ "description": "Require DPoP proofs for token/credential requests.",
20252
+ "type": "boolean"
20253
+ },
20254
+ "walletAttestationRequired": {
20255
+ "description": "Require wallet attestation for this authorization server.",
20256
+ "type": "boolean"
20257
+ },
20258
+ "walletProviderTrustLists": {
20259
+ "description": "Optional wallet provider trust list references for this authorization server.",
20260
+ "type": "array",
20261
+ "items": {
20262
+ "type": "object",
20263
+ "properties": {
20264
+ "trustListId": {
20265
+ "type": "string",
20266
+ "minLength": 1
20267
+ },
20268
+ "url": {
20269
+ "description": "URL of the wallet provider trust list.",
20270
+ "type": "string",
20271
+ "format": "uri"
20272
+ },
20273
+ "verifierKey": {
20274
+ "description": "Optional verifier key material used for trust list verification.",
20275
+ "type": "object",
20276
+ "propertyNames": {
20277
+ "type": "string"
20278
+ },
20279
+ "additionalProperties": {}
20280
+ },
20281
+ "verifierX509Der": {
20282
+ "description": "Optional verifier certificate in DER/base64 form.",
20283
+ "type": "string"
20284
+ }
20285
+ },
20286
+ "additionalProperties": false
20287
+ }
20288
+ },
20289
+ "label": {
20290
+ "description": "Optional display label for UI selection.",
20291
+ "type": "string"
20292
+ },
20293
+ "enabled": {
20294
+ "description": "Whether this authorization server entry is enabled.",
20295
+ "type": "boolean"
20296
+ }
20297
+ },
20298
+ "required": [
20299
+ "type",
20300
+ "id",
20301
+ "presentationConfigId"
20302
+ ],
20303
+ "additionalProperties": false
20304
+ },
20305
+ {
20306
+ "type": "object",
20307
+ "properties": {
20308
+ "type": {
20309
+ "type": "string",
20310
+ "const": "chained",
20311
+ "description": "Use upstream OIDC as authorization source."
20312
+ },
20313
+ "id": {
20314
+ "type": "string",
20315
+ "minLength": 1,
20316
+ "description": "Authorization server identifier."
20317
+ },
20318
+ "upstream": {
20319
+ "type": "object",
20320
+ "properties": {
20321
+ "issuer": {
20322
+ "type": "string",
20323
+ "format": "uri",
20324
+ "description": "Upstream OIDC issuer URL."
20325
+ },
20326
+ "clientId": {
20327
+ "type": "string",
20328
+ "minLength": 1,
20329
+ "description": "Client id for upstream OIDC authentication."
20330
+ },
20331
+ "clientSecret": {
20332
+ "description": "Optional client secret for upstream OIDC authentication.",
20333
+ "type": "string",
20334
+ "minLength": 1
20335
+ },
20336
+ "scopes": {
20337
+ "description": "Optional scopes requested from the upstream issuer.",
20338
+ "type": "array",
20339
+ "items": {
20340
+ "type": "string",
20341
+ "minLength": 1
20342
+ }
20343
+ }
20344
+ },
20345
+ "required": [
20346
+ "issuer",
20347
+ "clientId"
20348
+ ],
20349
+ "additionalProperties": false,
20350
+ "description": "Upstream OIDC connection settings."
20351
+ },
20352
+ "token": {
20353
+ "description": "Optional token issuance settings.",
20354
+ "type": "object",
20355
+ "properties": {
20356
+ "lifetimeSeconds": {
20357
+ "description": "Access token lifetime in seconds.",
20358
+ "type": "number",
20359
+ "minimum": 60
20360
+ },
20361
+ "signingKeyId": {
20362
+ "description": "Optional key chain id used to sign issued tokens.",
20363
+ "type": "string",
20364
+ "minLength": 1
20365
+ },
20366
+ "refreshTokenEnabled": {
20367
+ "description": "Enable issuing refresh tokens.",
20368
+ "type": "boolean"
20369
+ },
20370
+ "refreshTokenExpiresInSeconds": {
20371
+ "description": "Refresh token lifetime in seconds.",
20372
+ "type": "number",
20373
+ "minimum": 60
20374
+ }
20375
+ },
20376
+ "additionalProperties": false
20377
+ },
20378
+ "requireDPoP": {
20379
+ "description": "Require DPoP proofs for token/credential requests.",
20380
+ "type": "boolean"
20381
+ },
20382
+ "walletAttestationRequired": {
20383
+ "description": "Require wallet attestation for this authorization server.",
20384
+ "type": "boolean"
20385
+ },
20386
+ "walletProviderTrustLists": {
20387
+ "description": "Optional wallet provider trust list references for this authorization server.",
20388
+ "type": "array",
20389
+ "items": {
20390
+ "type": "object",
20391
+ "properties": {
20392
+ "trustListId": {
20393
+ "type": "string",
20394
+ "minLength": 1
20395
+ },
20396
+ "url": {
20397
+ "description": "URL of the wallet provider trust list.",
20398
+ "type": "string",
20399
+ "format": "uri"
20400
+ },
20401
+ "verifierKey": {
20402
+ "description": "Optional verifier key material used for trust list verification.",
20403
+ "type": "object",
20404
+ "propertyNames": {
20405
+ "type": "string"
20406
+ },
20407
+ "additionalProperties": {}
20408
+ },
20409
+ "verifierX509Der": {
20410
+ "description": "Optional verifier certificate in DER/base64 form.",
20411
+ "type": "string"
20412
+ }
20413
+ },
20414
+ "additionalProperties": false
20415
+ }
20416
+ },
20417
+ "label": {
20418
+ "description": "Optional display label for UI selection.",
20419
+ "type": "string"
20420
+ },
20421
+ "enabled": {
20422
+ "description": "Whether this authorization server entry is enabled.",
20423
+ "type": "boolean"
20424
+ }
20425
+ },
20426
+ "required": [
20427
+ "type",
20428
+ "id",
20429
+ "upstream"
20430
+ ],
20431
+ "additionalProperties": false
20432
+ },
20433
+ {
20434
+ "type": "object",
20435
+ "properties": {
20436
+ "type": {
20437
+ "type": "string",
20438
+ "const": "built-in",
20439
+ "description": "Use EUDIPLO built-in authorization server."
20440
+ },
20441
+ "id": {
20442
+ "type": "string",
20443
+ "minLength": 1,
20444
+ "description": "Authorization server identifier."
20445
+ },
20446
+ "token": {
20447
+ "description": "Optional token issuance settings.",
20448
+ "type": "object",
20449
+ "properties": {
20450
+ "lifetimeSeconds": {
20451
+ "description": "Access token lifetime in seconds.",
20452
+ "type": "number",
20453
+ "minimum": 60
20454
+ },
20455
+ "signingKeyId": {
20456
+ "description": "Optional key chain id used to sign issued tokens.",
20457
+ "type": "string",
20458
+ "minLength": 1
20459
+ },
20460
+ "refreshTokenEnabled": {
20461
+ "description": "Enable issuing refresh tokens.",
20462
+ "type": "boolean"
20463
+ },
20464
+ "refreshTokenExpiresInSeconds": {
20465
+ "description": "Refresh token lifetime in seconds.",
20466
+ "type": "number",
20467
+ "minimum": 60
20468
+ }
20469
+ },
20470
+ "additionalProperties": false
20471
+ },
20472
+ "requireDPoP": {
20473
+ "description": "Require DPoP proofs for token/credential requests.",
20474
+ "type": "boolean"
20475
+ },
20476
+ "walletAttestationRequired": {
20477
+ "description": "Require wallet attestation for this authorization server.",
20478
+ "type": "boolean"
20479
+ },
20480
+ "walletProviderTrustLists": {
20481
+ "description": "Optional wallet provider trust list references for this authorization server.",
20482
+ "type": "array",
20483
+ "items": {
20484
+ "type": "object",
20485
+ "properties": {
20486
+ "trustListId": {
20487
+ "type": "string",
20488
+ "minLength": 1
20489
+ },
20490
+ "url": {
20491
+ "description": "URL of the wallet provider trust list.",
20492
+ "type": "string",
20493
+ "format": "uri"
20494
+ },
20495
+ "verifierKey": {
20496
+ "description": "Optional verifier key material used for trust list verification.",
20497
+ "type": "object",
20498
+ "propertyNames": {
20499
+ "type": "string"
20500
+ },
20501
+ "additionalProperties": {}
20502
+ },
20503
+ "verifierX509Der": {
20504
+ "description": "Optional verifier certificate in DER/base64 form.",
20505
+ "type": "string"
20506
+ }
20507
+ },
20508
+ "additionalProperties": false
20509
+ }
20510
+ },
20511
+ "label": {
20512
+ "description": "Optional display label for UI selection.",
20513
+ "type": "string"
20514
+ },
20515
+ "enabled": {
20516
+ "description": "Whether this authorization server entry is enabled.",
20517
+ "type": "boolean"
20518
+ }
20519
+ },
20520
+ "required": [
20521
+ "type",
20522
+ "id"
20523
+ ],
20524
+ "additionalProperties": false
20525
+ }
20526
+ ],
20527
+ "description": "Supported authorization server configurations."
20528
+ },
20529
+ "description": "Configured authorization server entries."
20530
+ },
20531
+ "federation": {
20532
+ "description": "Optional OpenID Federation settings.",
20533
+ "anyOf": [
20534
+ {
20535
+ "type": "object",
20536
+ "properties": {
20537
+ "role": {
20538
+ "description": "Federation role for this issuer.",
20539
+ "type": "string",
20540
+ "enum": [
20541
+ "trust_anchor",
20542
+ "intermediate",
20543
+ "leaf"
20544
+ ]
20545
+ },
20546
+ "mode": {
20547
+ "description": "Federation operation mode.",
20548
+ "type": "string",
20549
+ "enum": [
20550
+ "federation-only",
20551
+ "hybrid"
20552
+ ]
20553
+ },
20554
+ "entityId": {
20555
+ "description": "Optional local federation entity id.",
20556
+ "type": "string"
20557
+ },
20558
+ "enforceSigningPolicy": {
20559
+ "description": "Enforce strict signing policy checks.",
20560
+ "type": "boolean"
20561
+ },
20562
+ "cacheTtlSeconds": {
20563
+ "description": "Cache time-to-live for federation metadata in seconds.",
20564
+ "type": "integer",
20565
+ "minimum": 1,
20566
+ "maximum": 9007199254740991
20567
+ },
20568
+ "trustAnchors": {
20569
+ "type": "array",
20570
+ "items": {
20571
+ "type": "object",
20572
+ "properties": {
20573
+ "entityId": {
20574
+ "type": "string",
20575
+ "minLength": 1,
20576
+ "description": "Federation trust anchor entity id."
20577
+ },
20578
+ "entityConfigurationUri": {
20579
+ "type": "string",
20580
+ "format": "uri",
20581
+ "description": "Entity configuration URI for the trust anchor."
20582
+ }
20583
+ },
20584
+ "required": [
20585
+ "entityId",
20586
+ "entityConfigurationUri"
20587
+ ],
20588
+ "additionalProperties": false
20589
+ },
20590
+ "description": "Federation trust anchors."
20591
+ }
20592
+ },
20593
+ "required": [
20594
+ "trustAnchors"
20595
+ ],
20596
+ "additionalProperties": false
20597
+ },
20598
+ {
20599
+ "type": "null"
20600
+ }
20601
+ ]
20602
+ },
20603
+ "registrationCertificate": {
20604
+ "description": "Optional registration certificate settings.",
20605
+ "anyOf": [
20606
+ {
20607
+ "type": "object",
20608
+ "properties": {
20609
+ "enabled": {
20610
+ "description": "Enable issuer registration certificate support.",
20611
+ "type": "boolean"
20612
+ },
20613
+ "mode": {
20614
+ "description": "How registration certificate data is provided.",
20615
+ "type": "string",
20616
+ "enum": [
20617
+ "import",
20618
+ "generate"
20619
+ ]
20620
+ },
20621
+ "jwt": {
20622
+ "description": "Optional registration certificate JWT when using import mode.",
20623
+ "type": "string"
20624
+ },
20625
+ "privacyPolicy": {
20626
+ "description": "Optional privacy policy URI.",
20627
+ "type": "string"
20628
+ },
20629
+ "supportUri": {
20630
+ "description": "Optional support URI.",
20631
+ "type": "string"
20632
+ }
20633
+ },
20634
+ "additionalProperties": false
20635
+ },
20636
+ {
20637
+ "type": "null"
20638
+ }
20639
+ ]
20640
+ },
20641
+ "display": {
20642
+ "description": "Localized issuer metadata shown to wallets.",
20643
+ "type": "array",
20644
+ "items": {
20645
+ "type": "object",
20646
+ "properties": {
20647
+ "name": {
20648
+ "description": "Issuer display name.",
20649
+ "type": "string"
20650
+ },
20651
+ "locale": {
20652
+ "description": "Locale tag for this display entry.",
20653
+ "type": "string"
20654
+ },
20655
+ "logo": {
20656
+ "description": "Optional issuer logo metadata.",
20657
+ "type": "object",
20658
+ "properties": {
20659
+ "uri": {
20660
+ "type": "string",
20661
+ "minLength": 1,
20662
+ "description": "Logo URI."
20663
+ },
20664
+ "alt_text": {
20665
+ "description": "Optional localized alternative text.",
20666
+ "type": "string"
20667
+ }
20668
+ },
20669
+ "required": [
20670
+ "uri"
20671
+ ],
20672
+ "additionalProperties": {}
20673
+ }
20674
+ },
20675
+ "additionalProperties": {}
20676
+ }
20677
+ },
20678
+ "notificationEndpointEnabled": {
20679
+ "description": "Whether the OID4VCI notification endpoint is exposed for this issuance configuration.",
20680
+ "type": "boolean"
20681
+ },
20682
+ "credentialResponseEncryption": {
20683
+ "description": "Enable encrypted credential responses.",
20684
+ "type": "boolean"
20685
+ },
20686
+ "credentialRequestEncryption": {
20687
+ "description": "Require encrypted credential requests.",
20688
+ "type": "boolean"
20689
+ },
20690
+ "txCodeMaxAttempts": {
20691
+ "description": "Maximum verification attempts for transaction codes. Null resets to defaults.",
20692
+ "anyOf": [
20693
+ {
20694
+ "type": "integer",
20695
+ "minimum": 1,
20696
+ "maximum": 9007199254740991
20697
+ },
20698
+ {
20699
+ "type": "null"
20700
+ }
20701
+ ]
20702
+ },
20703
+ "offerLifetimeSeconds": {
20704
+ "description": "Default lifetime of credential offers in seconds. Can be overridden per offer request. Null or unset: offers do not expire.",
20705
+ "anyOf": [
20706
+ {
20707
+ "type": "integer",
20708
+ "minimum": 1,
20709
+ "maximum": 9007199254740991
20710
+ },
20711
+ {
20712
+ "type": "null"
20713
+ }
20714
+ ]
20715
+ }
20716
+ },
20717
+ "required": [
20718
+ "authorizationServers"
20719
+ ],
20720
+ "additionalProperties": false,
20721
+ "title": "IssuanceConfig"
20722
+ }
20723
+ }
20724
+ },
20725
+ {
20726
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
20727
+ "$id": "https://eudiplo.dev/schemas/v2/PresentationConfigFile.schema.json",
20728
+ "title": "PresentationConfigFile",
20729
+ "type": "object",
20730
+ "properties": {
20731
+ "$schema": {
20732
+ "type": "string",
20733
+ "const": "https://eudiplo.dev/schemas/v2/PresentationConfigFile.schema.json"
20734
+ },
20735
+ "metadata": {
20736
+ "type": "object",
20737
+ "properties": {
20738
+ "generation": {
20739
+ "type": "integer",
20740
+ "minimum": 1,
20741
+ "description": "Monotonically increasing configuration generation."
20742
+ },
20743
+ "ownership": {
20744
+ "type": "string",
20745
+ "enum": [
20746
+ "unmanaged",
20747
+ "file-managed"
20748
+ ],
20749
+ "description": "Requested ownership recorded when the document is applied."
20750
+ }
20751
+ },
20752
+ "additionalProperties": false
20753
+ },
20754
+ "spec": {
20755
+ "allOf": [
20756
+ {
20757
+ "$ref": "#/$defs/PresentationConfigCreateDto"
20758
+ },
20759
+ {
20760
+ "type": "object",
20761
+ "required": [
20762
+ "id"
20763
+ ],
20764
+ "properties": {
20765
+ "id": {
20766
+ "type": "string",
20767
+ "minLength": 1
20768
+ }
20769
+ }
20770
+ }
20771
+ ]
20772
+ }
20773
+ },
20774
+ "required": [
20775
+ "$schema",
20776
+ "spec"
20777
+ ],
20778
+ "additionalProperties": false,
20779
+ "$defs": {
20780
+ "PresentationConfigCreateDto": {
20781
+ "type": "object",
20782
+ "properties": {
20783
+ "id": {
20784
+ "type": "string",
20785
+ "minLength": 1,
20786
+ "description": "Presentation configuration identifier."
20787
+ },
20788
+ "description": {
20789
+ "description": "Optional presentation configuration description.",
20790
+ "type": [
20791
+ "string",
20792
+ "null"
20793
+ ]
20794
+ },
20795
+ "lifeTime": {
20796
+ "description": "Presentation request lifetime in seconds.",
20797
+ "type": "integer",
20798
+ "minimum": 1,
20799
+ "maximum": 9007199254740991
20800
+ },
20801
+ "skewSeconds": {
20802
+ "description": "Clock skew tolerance in seconds.",
20803
+ "type": "integer",
20804
+ "minimum": 0,
20805
+ "maximum": 9007199254740991
20806
+ },
20807
+ "statusCheckMode": {
20808
+ "description": "Revocation/status check mode.",
20809
+ "type": "string",
20810
+ "enum": [
20811
+ "strict",
20812
+ "best_effort",
20813
+ "disabled"
20814
+ ]
20815
+ },
20816
+ "dcql_query": {
20817
+ "type": "object",
20818
+ "properties": {
20819
+ "credentials": {
20820
+ "minItems": 1,
20821
+ "type": "array",
20822
+ "items": {
20823
+ "oneOf": [
20824
+ {
20825
+ "type": "object",
20826
+ "properties": {
20827
+ "id": {
20828
+ "type": "string",
20829
+ "minLength": 1,
20830
+ "pattern": "^[A-Za-z0-9_-]+$",
20831
+ "description": "Credential query identifier."
20832
+ },
20833
+ "multiple": {
20834
+ "description": "Allow multiple matching credentials.",
20835
+ "type": "boolean"
20836
+ },
20837
+ "claim_sets": {
20838
+ "description": "Optional claim set constraints.",
20839
+ "type": "array",
20840
+ "items": {
20841
+ "type": "array",
20842
+ "items": {
20843
+ "type": "string"
20844
+ }
20845
+ }
20846
+ },
20847
+ "trusted_authorities": {
20848
+ "description": "Optional trusted authority constraints.",
20849
+ "type": "array",
20850
+ "items": {
20851
+ "oneOf": [
20852
+ {
20853
+ "type": "object",
20854
+ "properties": {
20855
+ "type": {
20856
+ "type": "string",
20857
+ "const": "etsi_tl",
20858
+ "description": "Trusted authority type discriminator for ETSI trust lists."
20859
+ },
20860
+ "values": {
20861
+ "type": "array",
20862
+ "items": {
20863
+ "type": "object",
20864
+ "properties": {
20865
+ "trustListId": {
20866
+ "description": "Optional trust list id reference.",
20867
+ "type": "string"
20868
+ },
20869
+ "url": {
20870
+ "description": "Optional trust list URL reference.",
20871
+ "anyOf": [
20872
+ {
20873
+ "type": "string",
20874
+ "format": "uri"
20875
+ },
20876
+ {
20877
+ "type": "string",
20878
+ "pattern": "^<TENANT_URL>(?:\\/.*)?$"
20879
+ }
20880
+ ]
20881
+ },
20882
+ "verifierKey": {
20883
+ "description": "Optional verifier key material.",
20884
+ "type": "object",
20885
+ "propertyNames": {
20886
+ "type": "string"
20887
+ },
20888
+ "additionalProperties": {}
20889
+ },
20890
+ "verifierX509Der": {
20891
+ "description": "Optional verifier certificate in DER/base64 form.",
20892
+ "type": "string"
20893
+ }
20894
+ },
20895
+ "additionalProperties": false
20896
+ },
20897
+ "description": "Trust list references for ETSI TL verification."
20898
+ }
20899
+ },
20900
+ "required": [
20901
+ "type",
20902
+ "values"
20903
+ ],
20904
+ "additionalProperties": false
20905
+ },
20906
+ {
20907
+ "type": "object",
20908
+ "properties": {
20909
+ "type": {
20910
+ "type": "string",
20911
+ "const": "openid_federation",
20912
+ "description": "Trusted authority type discriminator for OpenID Federation."
20913
+ },
20914
+ "values": {
20915
+ "type": "array",
20916
+ "items": {
20917
+ "type": "string"
20918
+ },
20919
+ "description": "OpenID Federation authority identifiers."
20920
+ }
20921
+ },
20922
+ "required": [
20923
+ "type",
20924
+ "values"
20925
+ ],
20926
+ "additionalProperties": false
20927
+ }
20928
+ ]
20929
+ }
20930
+ },
20931
+ "format": {
20932
+ "type": "string",
20933
+ "const": "dc+sd-jwt",
20934
+ "description": "Credential format discriminator."
20935
+ },
20936
+ "meta": {
20937
+ "type": "object",
20938
+ "properties": {
20939
+ "vct_values": {
20940
+ "minItems": 1,
20941
+ "type": "array",
20942
+ "items": {
20943
+ "type": "string"
20944
+ },
20945
+ "description": "Accepted VCT values."
20946
+ }
20947
+ },
20948
+ "required": [
20949
+ "vct_values"
20950
+ ],
20951
+ "additionalProperties": false
20952
+ },
20953
+ "claims": {
20954
+ "description": "Optional claim-level constraints.",
20955
+ "type": "array",
20956
+ "items": {
20957
+ "type": "object",
20958
+ "properties": {
20959
+ "id": {
20960
+ "description": "Optional claim query id.",
20961
+ "type": "string"
20962
+ },
20963
+ "path": {
20964
+ "type": "array",
20965
+ "items": {
20966
+ "type": [
20967
+ "string",
20968
+ "number"
20969
+ ]
20970
+ },
20971
+ "description": "Path to the claim value in presented credentials."
20972
+ },
20973
+ "values": {
20974
+ "description": "Optional allowed values for the claim.",
20975
+ "type": "array",
20976
+ "items": {
20977
+ "type": "string"
20978
+ }
20979
+ }
20980
+ },
20981
+ "required": [
20982
+ "path"
20983
+ ],
20984
+ "additionalProperties": false
20985
+ }
20986
+ }
20987
+ },
20988
+ "required": [
20989
+ "id",
20990
+ "format",
20991
+ "meta"
20992
+ ],
20993
+ "additionalProperties": false
20994
+ },
20995
+ {
20996
+ "type": "object",
20997
+ "properties": {
20998
+ "id": {
20999
+ "type": "string",
21000
+ "minLength": 1,
21001
+ "pattern": "^[A-Za-z0-9_-]+$",
21002
+ "description": "Credential query identifier."
21003
+ },
21004
+ "multiple": {
21005
+ "description": "Allow multiple matching credentials.",
21006
+ "type": "boolean"
21007
+ },
21008
+ "claim_sets": {
21009
+ "description": "Optional claim set constraints.",
21010
+ "type": "array",
21011
+ "items": {
21012
+ "type": "array",
21013
+ "items": {
21014
+ "type": "string"
21015
+ }
21016
+ }
21017
+ },
21018
+ "trusted_authorities": {
21019
+ "description": "Optional trusted authority constraints.",
21020
+ "type": "array",
21021
+ "items": {
21022
+ "oneOf": [
21023
+ {
21024
+ "type": "object",
21025
+ "properties": {
21026
+ "type": {
21027
+ "type": "string",
21028
+ "const": "etsi_tl",
21029
+ "description": "Trusted authority type discriminator for ETSI trust lists."
21030
+ },
21031
+ "values": {
21032
+ "type": "array",
21033
+ "items": {
21034
+ "type": "object",
21035
+ "properties": {
21036
+ "trustListId": {
21037
+ "description": "Optional trust list id reference.",
21038
+ "type": "string"
21039
+ },
21040
+ "url": {
21041
+ "description": "Optional trust list URL reference.",
21042
+ "anyOf": [
21043
+ {
21044
+ "type": "string",
21045
+ "format": "uri"
21046
+ },
21047
+ {
21048
+ "type": "string",
21049
+ "pattern": "^<TENANT_URL>(?:\\/.*)?$"
21050
+ }
21051
+ ]
21052
+ },
21053
+ "verifierKey": {
21054
+ "description": "Optional verifier key material.",
21055
+ "type": "object",
21056
+ "propertyNames": {
21057
+ "type": "string"
21058
+ },
21059
+ "additionalProperties": {}
21060
+ },
21061
+ "verifierX509Der": {
21062
+ "description": "Optional verifier certificate in DER/base64 form.",
21063
+ "type": "string"
21064
+ }
21065
+ },
21066
+ "additionalProperties": false
21067
+ },
21068
+ "description": "Trust list references for ETSI TL verification."
21069
+ }
21070
+ },
21071
+ "required": [
21072
+ "type",
21073
+ "values"
21074
+ ],
21075
+ "additionalProperties": false
21076
+ },
21077
+ {
21078
+ "type": "object",
21079
+ "properties": {
21080
+ "type": {
21081
+ "type": "string",
21082
+ "const": "openid_federation",
21083
+ "description": "Trusted authority type discriminator for OpenID Federation."
21084
+ },
21085
+ "values": {
21086
+ "type": "array",
21087
+ "items": {
21088
+ "type": "string"
21089
+ },
21090
+ "description": "OpenID Federation authority identifiers."
21091
+ }
21092
+ },
21093
+ "required": [
21094
+ "type",
21095
+ "values"
21096
+ ],
21097
+ "additionalProperties": false
21098
+ }
21099
+ ]
21100
+ }
21101
+ },
21102
+ "format": {
21103
+ "type": "string",
21104
+ "const": "mso_mdoc",
21105
+ "description": "Credential format discriminator."
21106
+ },
21107
+ "meta": {
21108
+ "type": "object",
21109
+ "properties": {
21110
+ "doctype_value": {
21111
+ "type": "string",
21112
+ "minLength": 1,
21113
+ "description": "Expected mDoc doctype value."
21114
+ }
21115
+ },
21116
+ "required": [
21117
+ "doctype_value"
21118
+ ],
21119
+ "additionalProperties": false
21120
+ },
21121
+ "claims": {
21122
+ "description": "Optional mDoc claim-level constraints.",
21123
+ "type": "array",
21124
+ "items": {
21125
+ "type": "object",
21126
+ "properties": {
21127
+ "id": {
21128
+ "description": "Optional claim query id.",
21129
+ "type": "string"
21130
+ },
21131
+ "path": {
21132
+ "type": "array",
21133
+ "items": {
21134
+ "type": [
21135
+ "string",
21136
+ "number"
21137
+ ]
21138
+ },
21139
+ "description": "Path to the claim value in presented credentials."
21140
+ },
21141
+ "values": {
21142
+ "description": "Optional allowed values for the claim.",
21143
+ "type": "array",
21144
+ "items": {
21145
+ "type": "string"
21146
+ }
21147
+ },
21148
+ "intent_to_retain": {
21149
+ "description": "Whether relying party intends to retain the claim.",
21150
+ "type": "boolean"
21151
+ }
21152
+ },
21153
+ "required": [
21154
+ "path"
21155
+ ],
21156
+ "additionalProperties": false
21157
+ }
21158
+ }
21159
+ },
21160
+ "required": [
21161
+ "id",
21162
+ "format",
21163
+ "meta"
21164
+ ],
21165
+ "additionalProperties": false
21166
+ }
21167
+ ]
21168
+ },
21169
+ "description": "Credential queries requested by the verifier."
21170
+ },
21171
+ "credential_sets": {
21172
+ "description": "Optional higher-level credential set requirements.",
21173
+ "type": "array",
21174
+ "items": {
21175
+ "type": "object",
21176
+ "properties": {
21177
+ "options": {
21178
+ "minItems": 1,
21179
+ "type": "array",
21180
+ "items": {
21181
+ "minItems": 1,
21182
+ "type": "array",
21183
+ "items": {
21184
+ "type": "string"
21185
+ }
21186
+ },
21187
+ "description": "Alternative credential query id combinations."
21188
+ },
21189
+ "required": {
21190
+ "description": "Whether this credential set is mandatory.",
21191
+ "type": "boolean"
21192
+ }
21193
+ },
21194
+ "required": [
21195
+ "options"
21196
+ ],
21197
+ "additionalProperties": false
21198
+ }
21199
+ }
21200
+ },
21201
+ "required": [
21202
+ "credentials"
21203
+ ],
21204
+ "additionalProperties": false,
21205
+ "description": "DCQL query defining requested credentials and claims."
21206
+ },
21207
+ "transaction_data": {
21208
+ "description": "Optional transaction data descriptors.",
21209
+ "anyOf": [
21210
+ {
21211
+ "type": "array",
21212
+ "items": {
21213
+ "type": "object",
21214
+ "properties": {
21215
+ "type": {
21216
+ "type": "string",
21217
+ "description": "Transaction data type identifier."
21218
+ },
21219
+ "credential_ids": {
21220
+ "type": "array",
21221
+ "items": {
21222
+ "type": "string"
21223
+ },
21224
+ "description": "Credential query ids this transaction data applies to."
21225
+ },
21226
+ "payload": {
21227
+ "description": "Transaction details. Required for TS12 SCA transaction data."
21228
+ }
21229
+ },
21230
+ "required": [
21231
+ "type",
21232
+ "credential_ids"
21233
+ ],
21234
+ "additionalProperties": {}
21235
+ }
21236
+ },
21237
+ {
21238
+ "type": "null"
21239
+ }
21240
+ ]
21241
+ },
21242
+ "registration_cert": {
21243
+ "description": "Optional registration certificate request settings.",
21244
+ "anyOf": [
21245
+ {
21246
+ "type": "object",
21247
+ "properties": {
21248
+ "id": {
21249
+ "type": "string"
21250
+ },
21251
+ "body": {
21252
+ "type": "object",
21253
+ "properties": {
21254
+ "privacy_policy": {
21255
+ "type": "string"
21256
+ },
21257
+ "support_uri": {
21258
+ "type": "string"
21259
+ },
21260
+ "intermediary": {
21261
+ "type": "string"
21262
+ },
21263
+ "purpose": {
21264
+ "type": "array",
21265
+ "items": {
21266
+ "type": "object",
21267
+ "properties": {
21268
+ "lang": {
21269
+ "type": "string"
21270
+ },
21271
+ "content": {
21272
+ "type": "string"
21273
+ }
21274
+ },
21275
+ "required": [
21276
+ "lang",
21277
+ "content"
21278
+ ],
21279
+ "additionalProperties": false
21280
+ }
21281
+ },
21282
+ "credentials": {
21283
+ "type": "array",
21284
+ "items": {
21285
+ "type": "object",
21286
+ "propertyNames": {
21287
+ "type": "string"
21288
+ },
21289
+ "additionalProperties": {}
21290
+ }
21291
+ },
21292
+ "provides_attestations": {
21293
+ "type": "array",
21294
+ "items": {
21295
+ "type": "string",
21296
+ "minLength": 1
21297
+ }
21298
+ }
21299
+ },
21300
+ "additionalProperties": false
21301
+ },
21302
+ "jwt": {
21303
+ "type": "string"
21304
+ }
21305
+ },
21306
+ "additionalProperties": false
21307
+ },
21308
+ {
21309
+ "type": "null"
21310
+ }
21311
+ ]
21312
+ },
21313
+ "registrationCertImportJwt": {
21314
+ "description": "Optional imported registration certificate JWT.",
21315
+ "type": [
21316
+ "string",
21317
+ "null"
21318
+ ]
21319
+ },
21320
+ "registrationCertImportId": {
21321
+ "description": "Optional registrar-side registration certificate id.",
21322
+ "type": [
21323
+ "string",
21324
+ "null"
21325
+ ]
21326
+ },
21327
+ "registrationCertBodyPrivacyPolicy": {
21328
+ "description": "Optional registration certificate privacy policy URI.",
21329
+ "type": [
21330
+ "string",
21331
+ "null"
21332
+ ]
21333
+ },
21334
+ "registrationCertBodySupportUri": {
21335
+ "description": "Optional registration certificate support URI.",
21336
+ "type": [
21337
+ "string",
21338
+ "null"
21339
+ ]
21340
+ },
21341
+ "registrationCertBodyIntermediary": {
21342
+ "description": "Optional registration certificate intermediary.",
21343
+ "type": [
21344
+ "string",
21345
+ "null"
21346
+ ]
21347
+ },
21348
+ "registrationCertBodyPurpose": {
21349
+ "description": "Optional registration certificate purpose entries.",
21350
+ "anyOf": [
21351
+ {
21352
+ "type": "array",
21353
+ "items": {
21354
+ "type": "object",
21355
+ "properties": {
21356
+ "lang": {
21357
+ "type": "string"
21358
+ },
21359
+ "content": {
21360
+ "type": "string"
21361
+ }
21362
+ },
21363
+ "additionalProperties": false
21364
+ }
21365
+ },
21366
+ {
21367
+ "type": "null"
21368
+ }
21369
+ ]
21370
+ },
21371
+ "webhookEndpointId": {
21372
+ "description": "Optional webhook endpoint id for presentation callbacks.",
21373
+ "type": [
21374
+ "string",
21375
+ "null"
21376
+ ]
21377
+ },
21378
+ "attached": {
21379
+ "description": "Optional attachments included with presentation requests.",
21380
+ "anyOf": [
21381
+ {
21382
+ "type": "array",
21383
+ "items": {
21384
+ "type": "object",
21385
+ "properties": {
21386
+ "format": {
21387
+ "type": "string",
21388
+ "description": "Attachment format identifier."
21389
+ },
21390
+ "data": {
21391
+ "description": "Attachment payload."
21392
+ },
21393
+ "credential_ids": {
21394
+ "description": "Optional credential query ids bound to this attachment.",
21395
+ "type": "array",
21396
+ "items": {
21397
+ "type": "string"
21398
+ }
21399
+ }
21400
+ },
21401
+ "required": [
21402
+ "format",
21403
+ "data"
21404
+ ],
21405
+ "additionalProperties": false
21406
+ }
21407
+ },
21408
+ {
21409
+ "type": "null"
21410
+ }
21411
+ ]
21412
+ },
21413
+ "redirectUri": {
21414
+ "description": "Optional redirect URI after presentation completion.",
21415
+ "type": [
21416
+ "string",
21417
+ "null"
21418
+ ]
21419
+ },
21420
+ "accessKeyChainId": {
21421
+ "description": "Optional key chain id for access token/auth operations.",
21422
+ "type": [
21423
+ "string",
21424
+ "null"
21425
+ ]
21426
+ },
21427
+ "readerAuth": {
21428
+ "description": "Whether reader authentication is required for mDoc requests.",
21429
+ "type": [
21430
+ "boolean",
21431
+ "null"
21432
+ ]
21433
+ }
21434
+ },
21435
+ "required": [
21436
+ "id",
21437
+ "dcql_query"
21438
+ ],
21439
+ "additionalProperties": false,
21440
+ "title": "PresentationConfigCreateDto"
21441
+ }
21442
+ }
21443
+ }
21444
+ ];
21445
+
21446
+ // ../../packages/eudiplo-config-format/dist/config-validator.js
21447
+ var ajv = new import__.Ajv2020({
21448
+ allErrors: true,
21449
+ strict: false,
21450
+ validateFormats: false
21451
+ });
21452
+ for (const schema of CONFIG_SCHEMAS)
21453
+ ajv.addSchema(schema);
21454
+ function validateConfigDocument(document) {
21455
+ const file = serializeDocument(document);
21456
+ const validate = ajv.getSchema(file.$schema);
21457
+ if (!validate)
21458
+ throw new Error(`No bundled validator for ${file.$schema}`);
21459
+ const issues = [];
21460
+ if (!validate(file)) {
21461
+ for (const issue of validate.errors ?? [])
21462
+ issues.push({
21463
+ severity: "error",
21464
+ code: "CONFIG_SCHEMA_VALIDATION_FAILED",
21465
+ path: issue.instancePath || "/",
21466
+ message: issue.keyword === "additionalProperties" ? `Unknown property: ${String(issue.params.additionalProperty)}` : issue.message ?? "Invalid configuration",
21467
+ resource: { kind: document.kind, id: resourceId(document) }
21468
+ });
21469
+ }
21470
+ const id = document.kind === "Client" ? document.spec.clientId : document.spec.id;
21471
+ if (id !== void 0 && id !== resourceId(document))
21472
+ issues.push({
21473
+ severity: "error",
21474
+ code: "RESOURCE_ID_MISMATCH",
21475
+ path: document.kind === "Client" ? "/spec/clientId" : "/spec/id",
21476
+ message: "Resource identifier does not match metadata.id"
21477
+ });
21478
+ return issues;
21479
+ }
21480
+
21481
+ // src/commands/config/portability/migrations.ts
21482
+ function upgradeDocument(input) {
21483
+ const result = migrateDocument(input, validateConfigDocument);
21484
+ return { ...result, document: serializeDocument(result.document) };
21485
+ }
21486
+
21487
+ // src/commands/config/portability/upgrade.ts
21488
+ var codec = new ConfigBundleCodec();
21489
+ function parse3(text, path2) {
21490
+ try {
21491
+ return JSON.parse(text);
21492
+ } catch {
21493
+ throw new Error(`Invalid JSON in ${path2}`);
21494
+ }
21495
+ }
21496
+ function upgradeJson(input, file, context) {
21497
+ const bundle = Array.isArray(input?.documents);
21498
+ if (bundle) assertConfigBundle(input);
21499
+ const results = (bundle ? input.documents : [input]).map(
21500
+ (document) => upgradeDocument(document)
21501
+ );
21502
+ let blocked = false;
21503
+ for (const result of results) {
21504
+ for (const issue of result.issues) {
21505
+ context.stderr.write(
21506
+ `${file}${issue.path}: ${issue.severity} ${issue.code}: ${issue.message}
21507
+ `
21508
+ );
21509
+ if (issue.severity !== "warning") blocked = true;
21510
+ }
21511
+ for (const migration of result.migrations)
21512
+ context.stdout.write(`${file}: migration ${migration}
21513
+ `);
21514
+ }
21515
+ if (blocked) throw new Error(`${file}: upgrade blocked; no output written`);
21516
+ if (!bundle) return results[0].document;
21517
+ const documents = results.map(
21518
+ (result) => result.document
21519
+ );
21520
+ const resources = input.manifest.resources.map(
21521
+ (resource) => {
21522
+ const index = input.documents.findIndex(
21523
+ (candidate) => normalizeDocument(candidate).kind === resource.kind && resourceId(candidate) === resource.id
21524
+ );
21525
+ const document = documents[index];
21526
+ return {
21527
+ ...resource,
21528
+ id: resourceId(document),
21529
+ $schema: document.$schema,
21530
+ sha256: createHash2("sha256").update(JSON.stringify(document)).digest("hex")
21531
+ };
21532
+ }
21533
+ );
21534
+ const output = {
21535
+ ...input,
21536
+ manifest: { ...input.manifest, formatVersion: 2, resources },
21537
+ documents
21538
+ };
21539
+ assertConfigBundle(output);
21540
+ return output;
21541
+ }
21542
+ function report(input, output, file, parsed, context) {
21543
+ const changed = stableConfigJson(input) !== stableConfigJson(output);
21544
+ context.stdout.write(
21545
+ `${file}: ${changed ? "upgrade required" : "current"}
21546
+ `
21547
+ );
21548
+ if (parsed.flags.diff === true)
21549
+ for (const change of configChanges(input, output)) {
21550
+ context.stdout.write(
21551
+ ` ${change.path}: ${JSON.stringify(change.before) ?? "(absent)"} -> ${JSON.stringify(change.after) ?? "(absent)"}
21552
+ `
21553
+ );
21554
+ }
21555
+ return changed;
21556
+ }
21557
+ function inferredKind(path2) {
21558
+ const normalized = path2.split(sep2).join("/");
21559
+ const match = TENANT_RESOURCE_REGISTRY.find(
21560
+ (entry) => entry.kind === "file" ? normalized === entry.file || normalized.endsWith(`/${entry.file}`) : normalized.endsWith(`/${entry.subfolder}/${basename2(path2)}`) || normalized === `${entry.subfolder}/${basename2(path2)}`
21561
+ );
21562
+ return CONFIG_RESOURCE_KINDS.find(
21563
+ (kind) => `${CONFIG_FORMATS[kind].file}.schema.json` === match?.schemaFile
21564
+ );
21565
+ }
21566
+ function wrapBare(kind, input, path2) {
21567
+ if (!input || typeof input !== "object" || Array.isArray(input))
21568
+ throw new Error(`${path2}: configuration must be an object`);
21569
+ const singleton = {
21570
+ Tenant: "tenant",
21571
+ KmsConfig: "kms",
21572
+ RegistrarConfig: "registrar",
21573
+ IssuanceConfig: "issuance"
21574
+ };
21575
+ const spec = structuredClone(input);
21576
+ if (kind === "KeyChain" && spec.key && !spec.keySource) {
21577
+ spec.keySource = { type: "private-jwk", jwk: spec.key };
21578
+ delete spec.key;
21579
+ }
21580
+ const id = String(
21581
+ singleton[kind] ?? spec.id ?? spec.clientId ?? basename2(path2, ".json")
21582
+ );
21583
+ if (!singleton[kind]) spec[kind === "Client" ? "clientId" : "id"] = id;
21584
+ return { $schema: schemaUrl(kind, 1), metadata: { generation: 1 }, spec };
21585
+ }
21586
+ async function folderFiles(path2) {
21587
+ const files = [];
21588
+ for (const entry of await readdir(path2, { withFileTypes: true })) {
21589
+ if (entry.name.startsWith(".")) continue;
21590
+ const file = join4(path2, entry.name);
21591
+ if (entry.isSymbolicLink())
21592
+ throw new Error(`Config folder contains a symbolic link: ${file}`);
21593
+ if (entry.isDirectory()) files.push(...await folderFiles(file));
21594
+ else if (entry.isFile()) files.push(file);
21595
+ }
21596
+ return files.sort();
21597
+ }
21598
+ async function upgradeFolder(source, parsed, context) {
21599
+ const outputs = /* @__PURE__ */ new Map();
21600
+ let changed = 0;
21601
+ for (const file of await folderFiles(source)) {
21602
+ if (extname(file) !== ".json" || relative2(source, file).split(sep2).includes("images"))
21603
+ continue;
21604
+ const input = parse3(await readFile4(file, "utf8"), file);
21605
+ const kind = inferredKind(relative2(source, file));
21606
+ if (!kind && !isConfigDocument(input)) continue;
21607
+ const candidate = isConfigDocument(input) ? input : wrapBare(kind, input, file);
21608
+ const output = upgradeJson(candidate, file, context);
21609
+ if (kind && normalizeDocument(output).kind !== kind)
21610
+ throw new Error(`${file}: expected ${kind} configuration`);
21611
+ if (report(input, output, relative2(source, file), parsed, context))
21612
+ changed++;
21613
+ outputs.set(
21614
+ relative2(source, file),
21615
+ `${JSON.stringify(output, null, 2)}
21616
+ `
21617
+ );
21618
+ }
21619
+ if (!outputs.size)
21620
+ throw new Error(`No configuration documents found in ${source}`);
21621
+ context.stdout.write(
21622
+ `${outputs.size - changed} current, ${changed} require upgrading
21623
+ `
21624
+ );
21625
+ if (parsed.flags.check === true) return changed ? 1 : 0;
21626
+ if (parsed.flags["dry-run"] === true) return 0;
21627
+ const destination = resolve3(
21628
+ context.cwd,
21629
+ readStringFlag(parsed.flags, "output") ?? `${source}.upgraded`
21630
+ );
21631
+ const overlap = (parent, child) => {
21632
+ const path2 = relative2(parent, child);
21633
+ return path2 === "" || !path2.startsWith(`..${sep2}`) && path2 !== "..";
21634
+ };
21635
+ if (overlap(source, destination) || overlap(destination, source))
21636
+ throw new Error(
21637
+ "Folder output must be separate from the source directory"
21638
+ );
21639
+ await lstat(destination).then(
21640
+ () => {
21641
+ throw new Error(`Output already exists: ${destination}`);
21642
+ },
21643
+ (error) => {
21644
+ if (error.code !== "ENOENT") throw error;
21645
+ }
21646
+ );
21647
+ await mkdir3(dirname3(destination), { recursive: true });
21648
+ const staging = await mkdtemp(
21649
+ join4(dirname3(destination), ".eudiplo-upgrade-")
21650
+ );
21651
+ try {
21652
+ await cp(source, staging, {
21653
+ recursive: true,
21654
+ filter: (path2) => path2 === source || !relative2(source, path2).split(sep2).some((part) => part.startsWith("."))
21655
+ });
21656
+ for (const [path2, contents] of outputs)
21657
+ await atomicWriteFile(join4(staging, path2), contents);
21658
+ await rename2(staging, destination);
21659
+ context.stdout.write(
21660
+ `Wrote upgraded configuration folder to ${destination}
21661
+ `
21662
+ );
21663
+ } finally {
21664
+ await rm(staging, { recursive: true, force: true });
21665
+ }
21666
+ return 0;
21667
+ }
21668
+ async function upgradeFile(parsed, context) {
21669
+ const name = parsed.positionals[0];
20231
21670
  if (!name)
20232
21671
  throw new Error("Usage: eudiplo config upgrade <file-or-folder>");
20233
21672
  const source = resolve3(context.cwd, name);
@@ -20568,14 +22007,11 @@ function createComposeEnv(options) {
20568
22007
  `AUTH_CLIENT_ID=${escapeEnvValue(authClientId)}`,
20569
22008
  `AUTH_CLIENT_SECRET=${escapeEnvValue(authClientSecret)}`
20570
22009
  ];
20571
- lines.push(
20572
- "",
20573
- ...databaseEnv(database),
20574
- "",
20575
- ...storageEnv(storage),
20576
- "",
20577
- ...kmsEnv(kms)
20578
- );
22010
+ lines.push("", ...databaseEnv(database), "", ...storageEnv(storage));
22011
+ const kmsLines = kmsEnv(kms);
22012
+ if (kmsLines.length > 0) {
22013
+ lines.push("", ...kmsLines);
22014
+ }
20579
22015
  return `${lines.join("\n")}
20580
22016
  `;
20581
22017
  }
@@ -20638,13 +22074,9 @@ function storageEnv(storage) {
20638
22074
  }
20639
22075
  function kmsEnv(kms) {
20640
22076
  if (kms === "db") {
20641
- return ["KM_TYPE=db"];
22077
+ return [];
20642
22078
  }
20643
- return [
20644
- "KM_TYPE=vault",
20645
- "VAULT_ADDR=http://vault:8200",
20646
- "VAULT_TOKEN=root"
20647
- ];
22079
+ return ["VAULT_ADDR=http://vault:8200", "VAULT_TOKEN=root"];
20648
22080
  }
20649
22081
  function randomSecret() {
20650
22082
  return randomBytes(24).toString("base64url");
@@ -21031,7 +22463,10 @@ async function validateResourceFile(filePath, relativeFile, schemaFile, getValid
21031
22463
  delete spec.key;
21032
22464
  }
21033
22465
  if (!CONFIG_SINGLETON_IDS[kind])
21034
- spec[kind === "Client" ? "clientId" : "id"] ??= basename4(relativeFile, ".json");
22466
+ spec[kind === "Client" ? "clientId" : "id"] ??= basename4(
22467
+ relativeFile,
22468
+ ".json"
22469
+ );
21035
22470
  resolved = {
21036
22471
  $schema: schemaUrl(kind),
21037
22472
  metadata: { generation: 1 },
@@ -22726,7 +24161,7 @@ function createDeploymentCommands(context, setExitCode) {
22726
24161
  // package.json
22727
24162
  var package_default = {
22728
24163
  name: "@eudiplo/cli",
22729
- version: "8.1.0-main.a6a67b3",
24164
+ version: "8.1.0-main.b98cc00",
22730
24165
  description: "Deployment-aware command line tools for EUDIPLO",
22731
24166
  private: false,
22732
24167
  type: "module",
@@ -22746,8 +24181,10 @@ var package_default = {
22746
24181
  "build:sea:bundle": "pnpm assets:sync && pnpm assets:check && esbuild src/index.ts --bundle --platform=node --format=esm --target=node22.12 --alias:jsonc-parser=jsonc-parser/lib/esm/main.js --outfile=dist-sea/index.js",
22747
24182
  "build:sea": "node scripts/build-cli-sea.mjs",
22748
24183
  dev: "tsx src/index.ts",
22749
- test: "vitest run --project cli",
24184
+ test: "vitest run --root ../.. --project cli",
22750
24185
  lint: "biome lint .",
24186
+ format: "biome format --write .",
24187
+ "format:check": "biome format .",
22751
24188
  prepublishOnly: "pnpm build:publish"
22752
24189
  },
22753
24190
  keywords: [
@@ -22789,7 +24226,7 @@ var package_default = {
22789
24226
  esbuild: "^0.28.2",
22790
24227
  tsx: "^4.23.13",
22791
24228
  typescript: "^7.0.2",
22792
- vitest: "4.1.11"
24229
+ vitest: "5.0.2"
22793
24230
  }
22794
24231
  };
22795
24232
 
@@ -23056,7 +24493,7 @@ var apiReachabilityCheck = {
23056
24493
  run: ({ baseUrl, context }) => requireBaseUrl(
23057
24494
  "API reachability",
23058
24495
  baseUrl,
23059
- (url) => checkEndpoint("API reachability", url, "/api/docs", context)
24496
+ (url) => checkEndpoint("API reachability", url, "api/docs", context)
23060
24497
  )
23061
24498
  };
23062
24499
  var healthEndpointCheck = {
@@ -23064,7 +24501,7 @@ var healthEndpointCheck = {
23064
24501
  run: ({ baseUrl, context }) => requireBaseUrl(
23065
24502
  "health endpoint",
23066
24503
  baseUrl,
23067
- (url) => checkEndpoint("health endpoint", url, "/health", context)
24504
+ (url) => checkEndpoint("health endpoint", url, "health", context)
23068
24505
  )
23069
24506
  };
23070
24507
  var tlsCertificateCheck = {
@@ -23104,7 +24541,7 @@ var clientConnectivityCheck = {
23104
24541
  message: `${instance.clientUrl} is not a valid absolute URL`
23105
24542
  };
23106
24543
  }
23107
- return checkEndpoint("client connectivity", clientUrl, "/", context);
24544
+ return checkEndpoint("client connectivity", clientUrl, "", context);
23108
24545
  }
23109
24546
  };
23110
24547
  var versionCompatibilityCheck = {
@@ -23115,7 +24552,7 @@ var versionCompatibilityCheck = {
23115
24552
  return authUnavailable("version compatibility", token);
23116
24553
  }
23117
24554
  const response = await fetchAuthenticated(
23118
- new URL("version", withTrailingSlash(url)),
24555
+ new URL("api/version", withTrailingSlash(url)),
23119
24556
  token.accessToken,
23120
24557
  context
23121
24558
  );
@@ -23124,7 +24561,7 @@ var versionCompatibilityCheck = {
23124
24561
  return {
23125
24562
  name: "version compatibility",
23126
24563
  status: "skip",
23127
- message: "This backend does not expose /version, so compatibility cannot be checked."
24564
+ message: "This backend does not expose /api/version, so compatibility cannot be checked."
23128
24565
  };
23129
24566
  }
23130
24567
  return {
@@ -23152,7 +24589,10 @@ var kmsHealthCheck = {
23152
24589
  return authUnavailable("KMS providers", token);
23153
24590
  }
23154
24591
  const response = await fetchAuthenticated(
23155
- new URL("key-chain/providers/health", withTrailingSlash(url)),
24592
+ new URL(
24593
+ "api/key-chain/providers/health",
24594
+ withTrailingSlash(url)
24595
+ ),
23156
24596
  token.accessToken,
23157
24597
  context
23158
24598
  );
@@ -23262,7 +24702,7 @@ async function requireBaseUrl(name, baseUrl, run) {
23262
24702
  return run(baseUrl);
23263
24703
  }
23264
24704
  async function checkEndpoint(name, baseUrl, path2, context) {
23265
- const url = new URL(path2, baseUrl);
24705
+ const url = new URL(path2, withTrailingSlash(baseUrl));
23266
24706
  try {
23267
24707
  const response = await context.fetch(url, { method: "GET" });
23268
24708
  if (response.ok) {
@@ -23743,7 +25183,9 @@ function runInstanceList(config, context) {
23743
25183
  function runInstanceShow(config, parsed, context) {
23744
25184
  const name = parsed.positionals[0] ?? config.defaultInstance;
23745
25185
  if (!name) {
23746
- throw new Error("No instance selected. Specify a name or add an instance first.");
25186
+ throw new Error(
25187
+ "No instance selected. Specify a name or add an instance first."
25188
+ );
23747
25189
  }
23748
25190
  const instance = config.instances[name];
23749
25191
  if (!instance) {
@@ -24134,7 +25576,7 @@ function parseVersion(tag) {
24134
25576
  function compareVersions2(a, b) {
24135
25577
  return a.major - b.major || a.minor - b.minor || a.patch - b.patch;
24136
25578
  }
24137
- var migrationBaseUrl = "https://docs.eudiplo.dev/migration";
25579
+ var migrationBaseUrl = "https://docs.eudiplo.dev/upgrade";
24138
25580
  function migrationNotes(from, to) {
24139
25581
  const fromVersion = parseVersion(from);
24140
25582
  const toVersion = parseVersion(to);
@@ -24380,7 +25822,7 @@ function createProgram(context, setExitCode) {
24380
25822
  "Print the installed CLI version"
24381
25823
  ).helpCommand(true).addHelpText(
24382
25824
  "afterAll",
24383
- "\nFor more information, see https://docs.eudiplo.dev/getting-started/quick-start"
25825
+ "\nFor more information, see https://docs.eudiplo.dev/cookbooks/foundation"
24384
25826
  );
24385
25827
  program2.addCommand(createDemoCommand(context, setExitCode));
24386
25828
  program2.addCommand(createInitCommand(context, setExitCode));