@europeum-ebsi/cli 0.0.0 → 1.0.0-rc.0
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.
- package/LICENSE.txt +289 -289
- package/LICENSES.txt +538 -0
- package/README.md +1140 -98
- package/dist/api/client.d.ts +4 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +14 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/fetch.d.ts +13 -0
- package/dist/api/fetch.d.ts.map +1 -0
- package/dist/api/fetch.js +30 -0
- package/dist/api/fetch.js.map +1 -0
- package/dist/api/params.d.ts +4 -0
- package/dist/api/params.d.ts.map +1 -0
- package/dist/api/params.js +9 -0
- package/dist/api/params.js.map +1 -0
- package/dist/auth/dcql.d.ts +5 -0
- package/dist/auth/dcql.d.ts.map +1 -0
- package/dist/auth/dcql.js +41 -0
- package/dist/auth/dcql.js.map +1 -0
- package/dist/auth/presentation.d.ts +30 -0
- package/dist/auth/presentation.d.ts.map +1 -0
- package/dist/auth/presentation.js +99 -0
- package/dist/auth/presentation.js.map +1 -0
- package/dist/auth/token.d.ts +11 -0
- package/dist/auth/token.d.ts.map +1 -0
- package/dist/auth/token.js +116 -0
- package/dist/auth/token.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +96 -10
- package/dist/cli.js.map +1 -1
- package/dist/commands/auth.d.ts +3 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +99 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/config-cmd.d.ts +3 -0
- package/dist/commands/config-cmd.d.ts.map +1 -0
- package/dist/commands/config-cmd.js +86 -0
- package/dist/commands/config-cmd.js.map +1 -0
- package/dist/commands/contracts-registry.d.ts +3 -0
- package/dist/commands/contracts-registry.d.ts.map +1 -0
- package/dist/commands/contracts-registry.js +132 -0
- package/dist/commands/contracts-registry.js.map +1 -0
- package/dist/commands/did-registry.d.ts +3 -0
- package/dist/commands/did-registry.d.ts.map +1 -0
- package/dist/commands/did-registry.js +110 -0
- package/dist/commands/did-registry.js.map +1 -0
- package/dist/commands/faucet.d.ts +3 -0
- package/dist/commands/faucet.d.ts.map +1 -0
- package/dist/commands/faucet.js +78 -0
- package/dist/commands/faucet.js.map +1 -0
- package/dist/commands/health.d.ts +3 -0
- package/dist/commands/health.d.ts.map +1 -0
- package/dist/commands/health.js +20 -0
- package/dist/commands/health.js.map +1 -0
- package/dist/commands/issuers-registry.d.ts +3 -0
- package/dist/commands/issuers-registry.d.ts.map +1 -0
- package/dist/commands/issuers-registry.js +340 -0
- package/dist/commands/issuers-registry.js.map +1 -0
- package/dist/commands/ledger.d.ts +3 -0
- package/dist/commands/ledger.d.ts.map +1 -0
- package/dist/commands/ledger.js +549 -372
- package/dist/commands/ledger.js.map +1 -1
- package/dist/commands/onboarding.d.ts +3 -0
- package/dist/commands/onboarding.d.ts.map +1 -0
- package/dist/commands/onboarding.js +301 -0
- package/dist/commands/onboarding.js.map +1 -0
- package/dist/commands/openapi.d.ts +3 -0
- package/dist/commands/openapi.d.ts.map +1 -0
- package/dist/commands/openapi.js +37 -0
- package/dist/commands/openapi.js.map +1 -0
- package/dist/commands/policies-registry.d.ts +3 -0
- package/dist/commands/policies-registry.d.ts.map +1 -0
- package/dist/commands/policies-registry.js +198 -0
- package/dist/commands/policies-registry.js.map +1 -0
- package/dist/commands/registry.d.ts +27 -0
- package/dist/commands/registry.d.ts.map +1 -0
- package/dist/commands/registry.js +62 -0
- package/dist/commands/registry.js.map +1 -0
- package/dist/commands/schemas-registry.d.ts +3 -0
- package/dist/commands/schemas-registry.d.ts.map +1 -0
- package/dist/commands/schemas-registry.js +231 -0
- package/dist/commands/schemas-registry.js.map +1 -0
- package/dist/commands/shared/args.d.ts +2 -0
- package/dist/commands/shared/args.d.ts.map +1 -0
- package/dist/commands/shared/args.js +4 -0
- package/dist/commands/shared/args.js.map +1 -0
- package/dist/commands/shared/wallet-opts.d.ts +9 -0
- package/dist/commands/shared/wallet-opts.d.ts.map +1 -0
- package/dist/commands/shared/wallet-opts.js +44 -0
- package/dist/commands/shared/wallet-opts.js.map +1 -0
- package/dist/commands/timestamp.d.ts +3 -0
- package/dist/commands/timestamp.d.ts.map +1 -0
- package/dist/commands/timestamp.js +250 -0
- package/dist/commands/timestamp.js.map +1 -0
- package/dist/commands/track-and-trace.d.ts +3 -0
- package/dist/commands/track-and-trace.d.ts.map +1 -0
- package/dist/commands/track-and-trace.js +235 -0
- package/dist/commands/track-and-trace.js.map +1 -0
- package/dist/commands/wallet.d.ts +3 -0
- package/dist/commands/wallet.d.ts.map +1 -0
- package/dist/commands/wallet.js +123 -0
- package/dist/commands/wallet.js.map +1 -0
- package/dist/config/config.d.ts +45 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +111 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/ebsi-env.d.ts +4 -0
- package/dist/config/ebsi-env.d.ts.map +1 -0
- package/dist/config/ebsi-env.js +37 -0
- package/dist/config/ebsi-env.js.map +1 -0
- package/dist/crypto/wallet.d.ts +34 -0
- package/dist/crypto/wallet.d.ts.map +1 -0
- package/dist/crypto/wallet.js +100 -0
- package/dist/crypto/wallet.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -6
- package/dist/index.js.map +1 -1
- package/dist/ledger/read.d.ts +11 -0
- package/dist/ledger/read.d.ts.map +1 -0
- package/dist/ledger/read.js +24 -0
- package/dist/ledger/read.js.map +1 -0
- package/dist/ledger/registries.d.ts +25 -0
- package/dist/ledger/registries.d.ts.map +1 -0
- package/dist/ledger/registries.js +111 -0
- package/dist/ledger/registries.js.map +1 -0
- package/dist/ledger/write.d.ts +43 -0
- package/dist/ledger/write.d.ts.map +1 -0
- package/dist/ledger/write.js +119 -0
- package/dist/ledger/write.js.map +1 -0
- package/dist/onboarding/vc.d.ts +18 -0
- package/dist/onboarding/vc.d.ts.map +1 -0
- package/dist/onboarding/vc.js +72 -0
- package/dist/onboarding/vc.js.map +1 -0
- package/dist/output/format.d.ts +7 -0
- package/dist/output/format.d.ts.map +1 -0
- package/dist/output/format.js +94 -0
- package/dist/output/format.js.map +1 -0
- package/dist/tui/App.d.ts +3 -0
- package/dist/tui/App.d.ts.map +1 -0
- package/dist/tui/App.js +99 -0
- package/dist/tui/App.js.map +1 -0
- package/dist/tui/CommandPalette.d.ts +8 -0
- package/dist/tui/CommandPalette.d.ts.map +1 -0
- package/dist/tui/CommandPalette.js +105 -0
- package/dist/tui/CommandPalette.js.map +1 -0
- package/package.json +66 -108
- package/src/api/client.ts +26 -0
- package/src/api/fetch.ts +53 -0
- package/src/api/params.ts +17 -0
- package/src/auth/dcql.ts +84 -0
- package/src/auth/presentation.ts +255 -0
- package/src/auth/token.ts +244 -0
- package/src/cli.ts +164 -0
- package/src/commands/auth.ts +119 -0
- package/src/commands/config-cmd.ts +122 -0
- package/src/commands/contracts-registry.ts +156 -0
- package/src/commands/did-registry.ts +126 -0
- package/src/commands/faucet.ts +112 -0
- package/src/commands/health.ts +21 -0
- package/src/commands/issuers-registry.ts +385 -0
- package/src/commands/ledger.ts +777 -0
- package/src/commands/onboarding.ts +411 -0
- package/src/commands/openapi.ts +42 -0
- package/src/commands/policies-registry.ts +218 -0
- package/src/commands/registry.ts +152 -0
- package/src/commands/schemas-registry.ts +255 -0
- package/src/commands/shared/args.ts +14 -0
- package/src/commands/shared/wallet-opts.ts +85 -0
- package/src/commands/timestamp.ts +272 -0
- package/src/commands/track-and-trace.ts +263 -0
- package/src/commands/wallet.ts +175 -0
- package/src/config/config.ts +275 -0
- package/src/config/ebsi-env.ts +67 -0
- package/src/crypto/wallet.ts +291 -0
- package/src/index.ts +24 -0
- package/src/ledger/read.ts +70 -0
- package/src/ledger/registries.ts +285 -0
- package/src/ledger/write.ts +381 -0
- package/src/onboarding/vc.ts +205 -0
- package/src/output/format.ts +157 -0
- package/src/tui/App.tsx +282 -0
- package/src/tui/CommandPalette.tsx +223 -0
- package/bin/cli.js +0 -13
- package/dist/abi/pilot/DidRegistry.js +0 -568
- package/dist/abi/pilot/DidRegistry.js.map +0 -1
- package/dist/abi/pilot/Ptr.js +0 -666
- package/dist/abi/pilot/Ptr.js.map +0 -1
- package/dist/abi/pilot/SchemaSCRegistry.js +0 -264
- package/dist/abi/pilot/SchemaSCRegistry.js.map +0 -1
- package/dist/abi/pilot/Tcr.js +0 -715
- package/dist/abi/pilot/Tcr.js.map +0 -1
- package/dist/abi/pilot/Timestamp.js +0 -658
- package/dist/abi/pilot/Timestamp.js.map +0 -1
- package/dist/abi/pilot/Tir.js +0 -428
- package/dist/abi/pilot/Tir.js.map +0 -1
- package/dist/abi/pilot/TnT.js +0 -842
- package/dist/abi/pilot/TnT.js.map +0 -1
- package/dist/abi/pilot/Tpr.js +0 -492
- package/dist/abi/pilot/Tpr.js.map +0 -1
- package/dist/abi/test/DidRegistry.js +0 -568
- package/dist/abi/test/DidRegistry.js.map +0 -1
- package/dist/abi/test/Ptr.js +0 -666
- package/dist/abi/test/Ptr.js.map +0 -1
- package/dist/abi/test/SchemaSCRegistry.js +0 -300
- package/dist/abi/test/SchemaSCRegistry.js.map +0 -1
- package/dist/abi/test/Tcr.js +0 -715
- package/dist/abi/test/Tcr.js.map +0 -1
- package/dist/abi/test/Timestamp.js +0 -658
- package/dist/abi/test/Timestamp.js.map +0 -1
- package/dist/abi/test/Tir.js +0 -428
- package/dist/abi/test/Tir.js.map +0 -1
- package/dist/abi/test/TnT.js +0 -842
- package/dist/abi/test/TnT.js.map +0 -1
- package/dist/abi/test/Tpr.js +0 -492
- package/dist/abi/test/Tpr.js.map +0 -1
- package/dist/app.js +0 -659
- package/dist/app.js.map +0 -1
- package/dist/buildParam/didr.js +0 -374
- package/dist/buildParam/didr.js.map +0 -1
- package/dist/buildParam/index.js +0 -53
- package/dist/buildParam/index.js.map +0 -1
- package/dist/buildParam/ptr.js +0 -80
- package/dist/buildParam/ptr.js.map +0 -1
- package/dist/buildParam/tcr.js +0 -36
- package/dist/buildParam/tcr.js.map +0 -1
- package/dist/buildParam/timestamp.js +0 -350
- package/dist/buildParam/timestamp.js.map +0 -1
- package/dist/buildParam/tir.js +0 -110
- package/dist/buildParam/tir.js.map +0 -1
- package/dist/buildParam/tnt.js +0 -214
- package/dist/buildParam/tnt.js.map +0 -1
- package/dist/buildParam/tpr.js +0 -91
- package/dist/buildParam/tpr.js.map +0 -1
- package/dist/buildParam/tsr.js +0 -115
- package/dist/buildParam/tsr.js.map +0 -1
- package/dist/commands/authorisation.js +0 -144
- package/dist/commands/authorisation.js.map +0 -1
- package/dist/commands/compute.js +0 -680
- package/dist/commands/compute.js.map +0 -1
- package/dist/commands/conformance.js +0 -813
- package/dist/commands/conformance.js.map +0 -1
- package/dist/commands/hardwarewallet.js +0 -41
- package/dist/commands/hardwarewallet.js.map +0 -1
- package/dist/commands/index.js +0 -8
- package/dist/commands/index.js.map +0 -1
- package/dist/commands/ptr.js +0 -54
- package/dist/commands/ptr.js.map +0 -1
- package/dist/commands/tcr.js +0 -50
- package/dist/commands/tcr.js.map +0 -1
- package/dist/commands/tir.js +0 -64
- package/dist/commands/tir.js.map +0 -1
- package/dist/commands/tnl.js +0 -81
- package/dist/commands/tnl.js.map +0 -1
- package/dist/commands/tsr.js +0 -45
- package/dist/commands/tsr.js.map +0 -1
- package/dist/commands/view.js +0 -53
- package/dist/commands/view.js.map +0 -1
- package/dist/config.js +0 -497
- package/dist/config.js.map +0 -1
- package/dist/interfaces/context.js +0 -2
- package/dist/interfaces/context.js.map +0 -1
- package/dist/interfaces/contracts/ProxyFactory.js +0 -2
- package/dist/interfaces/contracts/ProxyFactory.js.map +0 -1
- package/dist/interfaces/contracts/ProxyTemplateRegistry.js +0 -2
- package/dist/interfaces/contracts/ProxyTemplateRegistry.js.map +0 -1
- package/dist/interfaces/contracts/SchemaSCRegistry.js +0 -2
- package/dist/interfaces/contracts/SchemaSCRegistry.js.map +0 -1
- package/dist/interfaces/contracts/common.js +0 -2
- package/dist/interfaces/contracts/common.js.map +0 -1
- package/dist/interfaces/index.js +0 -5
- package/dist/interfaces/index.js.map +0 -1
- package/dist/interfaces/jsonrpc.interface.js +0 -2
- package/dist/interfaces/jsonrpc.interface.js.map +0 -1
- package/dist/interfaces/paginated-list.interface.js +0 -2
- package/dist/interfaces/paginated-list.interface.js.map +0 -1
- package/dist/interfaces/unsigned-transaction.interface.js +0 -2
- package/dist/interfaces/unsigned-transaction.interface.js.map +0 -1
- package/dist/interfaces/utils.interface.js +0 -2
- package/dist/interfaces/utils.interface.js.map +0 -1
- package/dist/programs/migrateDid.js +0 -159
- package/dist/programs/migrateDid.js.map +0 -1
- package/dist/programs/migrateDids.js +0 -232
- package/dist/programs/migrateDids.js.map +0 -1
- package/dist/programs/migrateTsr.js +0 -201
- package/dist/programs/migrateTsr.js.map +0 -1
- package/dist/scripts/accreditAndAuthorize/conformance/step1 +0 -34
- package/dist/scripts/accreditAndAuthorize/conformance/step2 +0 -18
- package/dist/scripts/accreditAndAuthorize/conformance/step3 +0 -9
- package/dist/scripts/accreditAndAuthorize/conformance/step4 +0 -27
- package/dist/scripts/accreditAndAuthorize/conformance/step5 +0 -13
- package/dist/scripts/accreditAndAuthorize/conformance/step6 +0 -14
- package/dist/scripts/accreditAndAuthorize/conformance/step7 +0 -7
- package/dist/scripts/accreditAndAuthorize/test/step1 +0 -34
- package/dist/scripts/accreditAndAuthorize/test/step2 +0 -18
- package/dist/scripts/accreditAndAuthorize/test/step3 +0 -9
- package/dist/scripts/accreditAndAuthorize/test/step4 +0 -27
- package/dist/scripts/accreditAndAuthorize/test/step5 +0 -13
- package/dist/scripts/accreditAndAuthorize/test/step6 +0 -14
- package/dist/scripts/accreditAndAuthorize/test/step7 +0 -7
- package/dist/scripts/accreditTI +0 -21
- package/dist/scripts/assets/Nodes.json +0 -27
- package/dist/scripts/assets/vcdm1.1/CTRevocableCredential.json +0 -30
- package/dist/scripts/assets/vcdm1.1/CredentialToAttestVerifiableAuthorisationForTrustChain.json +0 -29
- package/dist/scripts/assets/vcdm1.1/Nodes.json +0 -27
- package/dist/scripts/assets/vcdm1.1/TrustedNodesList.json +0 -35
- package/dist/scripts/assets/vcdm1.1/VerifiableAccreditationToAccredit.json +0 -35
- package/dist/scripts/assets/vcdm1.1/VerifiableAccreditationToAttest.json +0 -33
- package/dist/scripts/assets/vcdm1.1/VerifiableAuthorisationForTrustChain.json +0 -22
- package/dist/scripts/assets/vcdm1.1/VerifiableAuthorisationToInvoke.json +0 -24
- package/dist/scripts/assets/vcdm1.1/VerifiableAuthorisationToOnboard.json +0 -24
- package/dist/scripts/assets/vcdm2.0/CredentialToAttestVerifiableAuthorisationForTrustChain.json +0 -29
- package/dist/scripts/assets/vcdm2.0/TrustedNodesList.json +0 -36
- package/dist/scripts/assets/vcdm2.0/VerifiableAccreditationToAccredit.json +0 -40
- package/dist/scripts/assets/vcdm2.0/VerifiableAccreditationToAttest.json +0 -38
- package/dist/scripts/assets/vcdm2.0/VerifiableAuthorisationForTrustChain.json +0 -30
- package/dist/scripts/assets/vcdm2.0/VerifiableAuthorisationToInvoke.json +0 -24
- package/dist/scripts/assets/vcdm2.0/VerifiableAuthorisationToOnboard.json +0 -23
- package/dist/scripts/bootstrap/0a-loadTPROperator +0 -5
- package/dist/scripts/bootstrap/0b-loadAdmin +0 -8
- package/dist/scripts/bootstrap/1-populateTPR +0 -92
- package/dist/scripts/bootstrap/2-populateDID +0 -6
- package/dist/scripts/bootstrap/3-populateTimestamp +0 -9
- package/dist/scripts/bootstrap/4-populateTIR +0 -8
- package/dist/scripts/bootstrap/5-populateTSR +0 -85
- package/dist/scripts/bootstrap/6-setupConformanceIssuer +0 -35
- package/dist/scripts/bootstrap/README.md +0 -218
- package/dist/scripts/issueVcInvoke +0 -10
- package/dist/scripts/issueVcOnboard +0 -9
- package/dist/scripts/issueVcRootTAO +0 -11
- package/dist/scripts/issueVcTAO +0 -12
- package/dist/scripts/issueVcTI +0 -12
- package/dist/scripts/issueVcTnl +0 -32
- package/dist/scripts/issue_CTRevocableCredential +0 -12
- package/dist/scripts/issue_SelfAttestationSupportOffice +0 -10
- package/dist/scripts/issue_VerifiableAccreditationToAccredit +0 -11
- package/dist/scripts/issue_VerifiableAccreditationToAttest +0 -11
- package/dist/scripts/issue_VerifiableAuthorisationForTrustChain +0 -10
- package/dist/scripts/issue_VerifiableAuthorisationToOnboard +0 -9
- package/dist/scripts/preregisterIssuer +0 -6
- package/dist/scripts/registerDidDocument +0 -15
- package/dist/scripts/registerIssuer +0 -6
- package/dist/scripts/updateVcRootTAO +0 -10
- package/dist/scripts/updateVcTAO +0 -11
- package/dist/scripts/updateVcTI +0 -11
- package/dist/scripts/vcdm2.0/issueSelfAttestationSupportOffice +0 -10
- package/dist/scripts/vcdm2.0/issueVcInvoke +0 -12
- package/dist/scripts/vcdm2.0/issueVcOnboard +0 -11
- package/dist/scripts/vcdm2.0/issueVcRootTAO +0 -14
- package/dist/scripts/vcdm2.0/issueVcTAO +0 -15
- package/dist/scripts/vcdm2.0/issueVcTI +0 -15
- package/dist/scripts/vcdm2.0/issueVcTnl +0 -34
- package/dist/scripts/vcdm2.0/registerDidDocument +0 -15
- package/dist/scripts/vcdm2.0/updateVcRootTAO +0 -13
- package/dist/scripts/vcdm2.0/updateVcTAO +0 -14
- package/dist/scripts/vcdm2.0/updateVcTI +0 -14
- package/dist/scripts/vcdm2.0/verifyVcTnl +0 -10
- package/dist/scripts/verifyVcTnl +0 -10
- package/dist/scripts/wct/accreditAndAuthorize +0 -133
- package/dist/scripts/wct/accreditAndAuthorize2 +0 -89
- package/dist/scripts/wct/holderWallet +0 -39
- package/dist/scripts/wct/holderWallet2 +0 -39
- package/dist/scripts/wct/issueToHolder +0 -38
- package/dist/scripts/wct/issueToHolder2 +0 -38
- package/dist/scripts/wct/pda1 +0 -3
- package/dist/scripts/wct/verifier +0 -8
- package/dist/scripts/wct/verifier2 +0 -7
- package/dist/utils/Client.js +0 -155
- package/dist/utils/Client.js.map +0 -1
- package/dist/utils/HardwareWallet.js +0 -326
- package/dist/utils/HardwareWallet.js.map +0 -1
- package/dist/utils/http.js +0 -132
- package/dist/utils/http.js.map +0 -1
- package/dist/utils/index.js +0 -8
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/jsonrpc.js +0 -38
- package/dist/utils/jsonrpc.js.map +0 -1
- package/dist/utils/print.js +0 -56
- package/dist/utils/print.js.map +0 -1
- package/dist/utils/utils.js +0 -427
- package/dist/utils/utils.js.map +0 -1
- package/dist/utils/vcdm.js +0 -47
- package/dist/utils/vcdm.js.map +0 -1
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { createVerifiablePresentationJwt } from "@europeum-ebsi/verifiable-presentation/vcdm11.js";
|
|
2
|
+
import { decodeJwt } from "jose";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
|
|
5
|
+
import type { CliConfig } from "../config/config.ts";
|
|
6
|
+
import type { WalletDetails } from "../crypto/wallet.ts";
|
|
7
|
+
|
|
8
|
+
import { buildEbsiEnvConfig } from "../config/ebsi-env.ts";
|
|
9
|
+
import {
|
|
10
|
+
buildDcqlVpToken,
|
|
11
|
+
createSelfAttestationVcJwt,
|
|
12
|
+
dcqlCredentialQueryId,
|
|
13
|
+
} from "./dcql.ts";
|
|
14
|
+
import {
|
|
15
|
+
buildPresentationSubmission,
|
|
16
|
+
requiresVc,
|
|
17
|
+
scopeFamilies,
|
|
18
|
+
} from "./presentation.ts";
|
|
19
|
+
|
|
20
|
+
const DID_REGISTRY_INVITE_FAMILY = "did-registry:invite";
|
|
21
|
+
|
|
22
|
+
export interface GetAccessTokenOptions {
|
|
23
|
+
config: CliConfig;
|
|
24
|
+
scope: string;
|
|
25
|
+
/**
|
|
26
|
+
* Which OpenID4VP grant to speak: `"draft14"` (default), the legacy
|
|
27
|
+
* Presentation Exchange grant, or `"1.0"`, the final DCQL grant. Both are
|
|
28
|
+
* accepted side by side by the Authorisation service; this only picks
|
|
29
|
+
* which one the CLI itself sends.
|
|
30
|
+
*/
|
|
31
|
+
spec?: "1.0" | "draft14";
|
|
32
|
+
vcJwt?: string;
|
|
33
|
+
wallet: WalletDetails;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Obtains an EBSI access token via the OIDC4VP `vp_token` grant flow.
|
|
38
|
+
*
|
|
39
|
+
* Mirrors the behaviour of `getAccessToken.ts` from the API test helpers.
|
|
40
|
+
*
|
|
41
|
+
* @param opts.scope - The EBSI scope string, e.g. "did-registry:write" or "issuers-registry:invite"
|
|
42
|
+
* @param opts.spec - Which grant to speak: "draft14" (default, legacy PEX) or "1.0" (DCQL)
|
|
43
|
+
* @param opts.vcJwt - A VC JWT to include in the VP (required for VC-required scopes)
|
|
44
|
+
* @param opts.wallet - Resolved wallet details; `wallet.signingKey()` picks the
|
|
45
|
+
* key that signs the VP (throws if both an ES256K and an ES256 key are
|
|
46
|
+
* configured with no --sign-alg to choose between them)
|
|
47
|
+
*/
|
|
48
|
+
export async function getAccessToken(
|
|
49
|
+
opts: GetAccessTokenOptions,
|
|
50
|
+
): Promise<string> {
|
|
51
|
+
const { config, scope, spec = "draft14", vcJwt, wallet } = opts;
|
|
52
|
+
|
|
53
|
+
if (!vcJwt && requiresVc(scope)) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
`Scope "${scope}" requires a Verifiable Credential. ` +
|
|
56
|
+
"Pass --vc <file> with a path to a VC JWT file.",
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Resolved once: throws when both keys are configured and no --sign-alg
|
|
61
|
+
// (or EBSI_SIGN_ALG / `ebsi config set signAlg`) chose one.
|
|
62
|
+
const signingKey = wallet.signingKey();
|
|
63
|
+
|
|
64
|
+
// `did-registry:invite`: the presented VerifiableAuthorisationToOnboard VC must
|
|
65
|
+
// authorise the signing key -- via `credentialSubject.jwkThumbprint` --
|
|
66
|
+
// or the Authorisation service will reject the request. Catch a mismatch
|
|
67
|
+
// here instead of round-tripping to the server, since it usually means
|
|
68
|
+
// either the wrong VC or the wrong key was passed.
|
|
69
|
+
if (vcJwt && scopeFamilies(scope).includes(DID_REGISTRY_INVITE_FAMILY)) {
|
|
70
|
+
const { vc } = decodeJwt(vcJwt) as {
|
|
71
|
+
vc?: { credentialSubject?: { jwkThumbprint?: unknown } };
|
|
72
|
+
};
|
|
73
|
+
const jwkThumbprint = vc?.credentialSubject?.jwkThumbprint;
|
|
74
|
+
|
|
75
|
+
if (!jwkThumbprint) {
|
|
76
|
+
throw new Error(
|
|
77
|
+
"The Verifiable Credential passed via --vc is missing " +
|
|
78
|
+
"credentialSubject.jwkThumbprint, which the Authorisation service " +
|
|
79
|
+
`requires for the "did-registry:invite" scope. Ask the issuer for a VC that ` +
|
|
80
|
+
`authorises this key (thumbprint: ${signingKey.thumbprint}).`,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (typeof jwkThumbprint !== "string") {
|
|
85
|
+
throw new TypeError(
|
|
86
|
+
"The Verifiable Credential passed via --vc has an invalid " +
|
|
87
|
+
"credentialSubject.jwkThumbprint property (not a string).",
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (jwkThumbprint !== signingKey.thumbprint) {
|
|
92
|
+
throw new Error(
|
|
93
|
+
"The Verifiable Credential passed via --vc authorises a different " +
|
|
94
|
+
`key (thumbprint: ${jwkThumbprint}) than the signing key ` +
|
|
95
|
+
`(thumbprint: ${signingKey.thumbprint}). Use the key the VC was ` +
|
|
96
|
+
"issued for, request a new VC for this key, or pass --sign-alg to " +
|
|
97
|
+
"select the intended key.",
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const { issuer, tokenEndpoint } = await discoverAuthEndpoints(config.baseUrl);
|
|
103
|
+
const ebsiEnvConfig = buildEbsiEnvConfig(config);
|
|
104
|
+
const nonce = randomUUID();
|
|
105
|
+
const now = Math.floor(Date.now() / 1000);
|
|
106
|
+
|
|
107
|
+
// On the OpenID4VP 1.0 (final)/DCQL grant, a combinable scope with no VC of
|
|
108
|
+
// its own (did-registry:write, issuers-registry:write, etc.) presents a self-issued placeholder
|
|
109
|
+
// credential instead of an empty VP -- DCQL requires `credentials` to be
|
|
110
|
+
// non-empty, unlike the legacy grant's `input_descriptors: []` (see
|
|
111
|
+
// `createSelfAttestationVcJwt`).
|
|
112
|
+
const dcqlSelfAttestationVc =
|
|
113
|
+
spec === "1.0" && !vcJwt
|
|
114
|
+
? createSelfAttestationVcJwt(signingKey)
|
|
115
|
+
: undefined;
|
|
116
|
+
|
|
117
|
+
// Mutually exclusive by construction: `dcqlSelfAttestationVc` is only ever
|
|
118
|
+
// built when `!vcJwt` (see above).
|
|
119
|
+
const credential = vcJwt ?? dcqlSelfAttestationVc;
|
|
120
|
+
|
|
121
|
+
const vpPayload = {
|
|
122
|
+
"@context": ["https://www.w3.org/2018/credentials/v1"],
|
|
123
|
+
holder: signingKey.issuer.did,
|
|
124
|
+
type: ["VerifiablePresentation"],
|
|
125
|
+
verifiableCredential: credential ? [credential] : [],
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const vpJwt = await createVerifiablePresentationJwt(
|
|
129
|
+
vpPayload,
|
|
130
|
+
signingKey.issuer,
|
|
131
|
+
issuer,
|
|
132
|
+
ebsiEnvConfig,
|
|
133
|
+
{
|
|
134
|
+
exp: now + 100,
|
|
135
|
+
// Needed only for "did-registry:invite": the holder DID isn't registered yet,
|
|
136
|
+
// so the server verifies the VP signature against this self-asserted
|
|
137
|
+
// header jwk instead of a DID Document. Every other scope's holder is
|
|
138
|
+
// already resolvable, so this would be superfluous there.
|
|
139
|
+
...(scopeFamilies(scope).includes(DID_REGISTRY_INVITE_FAMILY) && {
|
|
140
|
+
header: { jwk: signingKey.publicKeyJwk },
|
|
141
|
+
}),
|
|
142
|
+
nbf: now - 100,
|
|
143
|
+
nonce,
|
|
144
|
+
skipValidation: true,
|
|
145
|
+
},
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
if (spec === "1.0") {
|
|
149
|
+
// Every combinable family shares the same DCQL credential-query id
|
|
150
|
+
// (self_attestation_credential), so it doesn't matter which of a
|
|
151
|
+
// combined request's families is used to look it up.
|
|
152
|
+
const credentialQueryId = dcqlCredentialQueryId(scopeFamilies(scope)[0]!);
|
|
153
|
+
|
|
154
|
+
const body = new URLSearchParams({
|
|
155
|
+
grant_type: "vp_token",
|
|
156
|
+
scope: `openid ${scope}`,
|
|
157
|
+
vp_token: buildDcqlVpToken(credentialQueryId, vpJwt),
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
return submitTokenRequest(tokenEndpoint, body);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const submissionId = randomUUID();
|
|
164
|
+
const presentationSubmission = buildPresentationSubmission(
|
|
165
|
+
scope,
|
|
166
|
+
submissionId,
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
const body = new URLSearchParams({
|
|
170
|
+
grant_type: "vp_token",
|
|
171
|
+
presentation_submission: JSON.stringify(presentationSubmission),
|
|
172
|
+
scope: `openid ${scope}`,
|
|
173
|
+
vp_token: vpJwt,
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
return submitTokenRequest(tokenEndpoint, body);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Discovers the auth token endpoint from the authorisation service's
|
|
181
|
+
* OpenID Connect discovery document.
|
|
182
|
+
*
|
|
183
|
+
* Returns `{ issuer, tokenEndpoint }` where `issuer` is used as the VP audience.
|
|
184
|
+
*/
|
|
185
|
+
async function discoverAuthEndpoints(
|
|
186
|
+
baseUrl: string,
|
|
187
|
+
): Promise<{ issuer: string; tokenEndpoint: string }> {
|
|
188
|
+
const discoveryUrl = `${baseUrl}/auth/.well-known/openid-configuration`;
|
|
189
|
+
const resp = await fetch(discoveryUrl, {
|
|
190
|
+
headers: { Accept: "application/json" },
|
|
191
|
+
});
|
|
192
|
+
if (!resp.ok) {
|
|
193
|
+
throw new Error(
|
|
194
|
+
`Failed to fetch OpenID config from ${discoveryUrl}: HTTP ${resp.status.toString()}`,
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
const body = (await resp.json()) as {
|
|
198
|
+
issuer?: string;
|
|
199
|
+
token_endpoint?: string;
|
|
200
|
+
};
|
|
201
|
+
const { issuer, token_endpoint: tokenEndpoint } = body;
|
|
202
|
+
if (!issuer || !tokenEndpoint) {
|
|
203
|
+
throw new Error(
|
|
204
|
+
`OpenID config at ${discoveryUrl} is missing 'issuer' or 'token_endpoint'`,
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
return { issuer, tokenEndpoint };
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* POSTs a `vp_token` grant's form body to the token endpoint and extracts
|
|
212
|
+
* `access_token` from the response. Shared by both the legacy (draft 14) and
|
|
213
|
+
* 1.0 (final) OpenID4VP grants -- once the (differently-shaped) request body
|
|
214
|
+
* is built, submitting it and handling the response is identical either way.
|
|
215
|
+
*/
|
|
216
|
+
async function submitTokenRequest(
|
|
217
|
+
tokenEndpoint: string,
|
|
218
|
+
body: URLSearchParams,
|
|
219
|
+
): Promise<string> {
|
|
220
|
+
const resp = await fetch(tokenEndpoint, {
|
|
221
|
+
body: body.toString(),
|
|
222
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
223
|
+
method: "POST",
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
if (!resp.ok) {
|
|
227
|
+
let detail: string;
|
|
228
|
+
try {
|
|
229
|
+
const errBody = await resp.text();
|
|
230
|
+
detail = errBody;
|
|
231
|
+
} catch {
|
|
232
|
+
detail = `HTTP ${resp.status.toString()}`;
|
|
233
|
+
}
|
|
234
|
+
throw new Error(
|
|
235
|
+
`Token request failed (HTTP ${resp.status.toString()}): ${detail}`,
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const data = (await resp.json()) as { access_token?: string };
|
|
240
|
+
if (!data.access_token) {
|
|
241
|
+
throw new Error("Token response did not contain 'access_token'");
|
|
242
|
+
}
|
|
243
|
+
return data.access_token;
|
|
244
|
+
}
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
|
|
3
|
+
import { COMMANDS } from "./commands/registry.ts";
|
|
4
|
+
import { resolveConfig } from "./config/config.ts";
|
|
5
|
+
import { printError, printResult } from "./output/format.ts";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Builds and returns the Commander program.
|
|
9
|
+
*
|
|
10
|
+
* The command tree is assembled from the COMMANDS registry so that the same
|
|
11
|
+
* single source of truth drives both the non-interactive CLI and the TUI
|
|
12
|
+
* command palette.
|
|
13
|
+
*/
|
|
14
|
+
export function buildProgram(): Command {
|
|
15
|
+
const program = new Command();
|
|
16
|
+
|
|
17
|
+
program
|
|
18
|
+
.name("ebsi")
|
|
19
|
+
.description("EBSI Core CLI — interact with the EBSI Core API")
|
|
20
|
+
.version("1.0.0-rc.0")
|
|
21
|
+
// Global options inherited by all sub-commands
|
|
22
|
+
.option(
|
|
23
|
+
"--env <env>",
|
|
24
|
+
"EBSI environment (local, test, pilot, preprod, prod)",
|
|
25
|
+
)
|
|
26
|
+
.option("--base-url <url>", "Override the API base URL (incl. /v1 prefix)")
|
|
27
|
+
.option("--output <format>", "Output format: pretty (default), json, table")
|
|
28
|
+
.option(
|
|
29
|
+
"--token <jwt>",
|
|
30
|
+
"Bearer access token for authenticated requests (e.g. POST /ledger write methods). " +
|
|
31
|
+
"Also read from EBSI_ACCESS_TOKEN env var or `ebsi config set token <jwt>`.",
|
|
32
|
+
)
|
|
33
|
+
.option(
|
|
34
|
+
"--es256k-key <hex>",
|
|
35
|
+
"Secp256k1 private key (0x-prefixed hex). Mandatory for anything that signs: " +
|
|
36
|
+
"always signs Ethereum transactions, and signs VCs/VPs unless --sign-alg is ES256. " +
|
|
37
|
+
"Also read from EBSI_ES256K_PRIVATE_KEY env var or `ebsi config set es256kPrivateKey <hex>`. " +
|
|
38
|
+
"WARNING: passing keys on the command line may expose them in shell history.",
|
|
39
|
+
)
|
|
40
|
+
.option(
|
|
41
|
+
"--es256-key <hex>",
|
|
42
|
+
"P-256 private key (hex), optional — for signing VCs/VPs only (e.g. an `auth token` " +
|
|
43
|
+
"request). Also read from EBSI_ES256_PRIVATE_KEY env var or " +
|
|
44
|
+
"`ebsi config set es256PrivateKey <hex>`.",
|
|
45
|
+
)
|
|
46
|
+
.option(
|
|
47
|
+
"--sign-alg <alg>",
|
|
48
|
+
'Which key signs VCs/VPs: "ES256" or "ES256K". Required when both keys are ' +
|
|
49
|
+
"configured. Also read from EBSI_SIGN_ALG env var or `ebsi config set signAlg <alg>`.",
|
|
50
|
+
)
|
|
51
|
+
.option(
|
|
52
|
+
"--did <did>",
|
|
53
|
+
"EBSI DID (did:ebsi:...) to associate with the key(s). " +
|
|
54
|
+
"Also read from EBSI_DID env var or `ebsi config set did <did>`. " +
|
|
55
|
+
"If omitted when running `wallet create`, a new random DID is generated.",
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
// Build a sub-command tree from each descriptor's segment path, creating
|
|
59
|
+
// (or reusing) one Command node per segment so paths of any depth work —
|
|
60
|
+
// not just the "group", "group action", and "group sub action" shapes.
|
|
61
|
+
const nodes = new Map<string, Command>();
|
|
62
|
+
const configured = new Set<string>();
|
|
63
|
+
|
|
64
|
+
for (const descriptor of COMMANDS) {
|
|
65
|
+
let parent = program;
|
|
66
|
+
const path: string[] = [];
|
|
67
|
+
|
|
68
|
+
for (const [index, segment] of descriptor.segments.entries()) {
|
|
69
|
+
path.push(segment);
|
|
70
|
+
const key = path.join(".");
|
|
71
|
+
let node = nodes.get(key);
|
|
72
|
+
if (!node) {
|
|
73
|
+
node = new Command(segment).description(
|
|
74
|
+
index === 0
|
|
75
|
+
? `Commands for the ${descriptor.group} API`
|
|
76
|
+
: `${descriptor.group} ${path.slice(1).join(" ")} commands`,
|
|
77
|
+
);
|
|
78
|
+
parent.addCommand(node);
|
|
79
|
+
nodes.set(key, node);
|
|
80
|
+
}
|
|
81
|
+
parent = node;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const leafKey = descriptor.segments.join(".");
|
|
85
|
+
/* v8 ignore next -- no two command descriptors share a full segment path */
|
|
86
|
+
if (configured.has(leafKey)) continue;
|
|
87
|
+
configured.add(leafKey);
|
|
88
|
+
configureLeaf(parent, descriptor);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return program;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Attaches positional args, options, help text, and action handler to a leaf
|
|
96
|
+
* Commander command from a CommandDescriptor.
|
|
97
|
+
*/
|
|
98
|
+
function configureLeaf(
|
|
99
|
+
cmd: Command,
|
|
100
|
+
descriptor: (typeof COMMANDS)[number],
|
|
101
|
+
): void {
|
|
102
|
+
cmd.description(descriptor.summary);
|
|
103
|
+
|
|
104
|
+
for (const arg of descriptor.args) {
|
|
105
|
+
if (arg.required) {
|
|
106
|
+
cmd.argument(`<${arg.name}>`, arg.description);
|
|
107
|
+
} else {
|
|
108
|
+
cmd.argument(`[${arg.name}]`, arg.description);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
for (const opt of descriptor.options) {
|
|
113
|
+
cmd.option(opt.flags, opt.description, opt.defaultValue);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
cmd.action(async (...cmdArgs: unknown[]) => {
|
|
117
|
+
// Commander passes positional args first, then the Command instance
|
|
118
|
+
// (and any parent option values via parent chain)
|
|
119
|
+
const commandInstance = cmdArgs.at(-1) as Command;
|
|
120
|
+
|
|
121
|
+
// Collect positional arg values
|
|
122
|
+
const positional = cmdArgs.slice(0, descriptor.args.length) as string[];
|
|
123
|
+
const argMap: Record<string, string> = {};
|
|
124
|
+
for (const [i, arg] of descriptor.args.entries()) {
|
|
125
|
+
argMap[arg.name] = positional[i] ?? "";
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// optsWithGlobals() merges options from the entire parent chain
|
|
129
|
+
const mergedOpts =
|
|
130
|
+
commandInstance.optsWithGlobals<Record<string, string>>();
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
// resolveConfig can throw (e.g. the legacy EBSI_PRIVATE_KEY migration
|
|
134
|
+
// error, or an invalid --sign-alg) -- resolved inside this try so that,
|
|
135
|
+
// like every other command error, it goes through printError/exitCode
|
|
136
|
+
// instead of surfacing as an unhandled rejection. `config`/`config set`
|
|
137
|
+
// itself stays reachable even while that migration error would
|
|
138
|
+
// otherwise fire everywhere else, so the user has a way to fix it.
|
|
139
|
+
const config = resolveConfig(
|
|
140
|
+
Object.fromEntries(
|
|
141
|
+
Object.entries({
|
|
142
|
+
baseUrl: mergedOpts["baseUrl"],
|
|
143
|
+
did: mergedOpts["did"],
|
|
144
|
+
env: mergedOpts["env"],
|
|
145
|
+
es256Key: mergedOpts["es256Key"],
|
|
146
|
+
es256kKey: mergedOpts["es256kKey"],
|
|
147
|
+
output: mergedOpts["output"],
|
|
148
|
+
signAlg: mergedOpts["signAlg"],
|
|
149
|
+
token: mergedOpts["token"],
|
|
150
|
+
}).filter(([, v]) => v !== undefined),
|
|
151
|
+
),
|
|
152
|
+
{ allowLegacyPrivateKey: descriptor.segments[0] === "config" },
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
const data = await descriptor.handler(argMap, mergedOpts, config);
|
|
156
|
+
printResult(data, config.output);
|
|
157
|
+
} catch (error) {
|
|
158
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
159
|
+
const detail = error instanceof Error ? error.cause : error;
|
|
160
|
+
printError(message, detail);
|
|
161
|
+
process.exitCode = 1;
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
|
|
3
|
+
import type { CommandDescriptor } from "./registry.ts";
|
|
4
|
+
|
|
5
|
+
import { KNOWN_SCOPES, validateScope } from "../auth/presentation.ts";
|
|
6
|
+
import { getAccessToken } from "../auth/token.ts";
|
|
7
|
+
import { setPersistedConfigValue } from "../config/config.ts";
|
|
8
|
+
import { resolveWallet, WALLET_KEY_OPTIONS } from "./shared/wallet-opts.ts";
|
|
9
|
+
|
|
10
|
+
export const authCommands: CommandDescriptor[] = [
|
|
11
|
+
{
|
|
12
|
+
args: [],
|
|
13
|
+
group: "Auth",
|
|
14
|
+
async handler(_args, opts, config) {
|
|
15
|
+
const scope = opts["scope"];
|
|
16
|
+
if (!scope) {
|
|
17
|
+
throw new Error(
|
|
18
|
+
"Missing --scope. Provide one of: " + KNOWN_SCOPES.join(", "),
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
// Throws a descriptive error for unknown scopes, duplicates, or an
|
|
22
|
+
// illegal combination (e.g. mixing an invite scope with a write scope).
|
|
23
|
+
validateScope(scope);
|
|
24
|
+
|
|
25
|
+
const wallet = await resolveWallet(opts, config);
|
|
26
|
+
|
|
27
|
+
// Load VC from file if provided
|
|
28
|
+
let vcJwt: string | undefined;
|
|
29
|
+
const vcFile = opts["vc"];
|
|
30
|
+
if (vcFile) {
|
|
31
|
+
try {
|
|
32
|
+
vcJwt = readFileSync(vcFile, "utf8").trim();
|
|
33
|
+
} catch (error) {
|
|
34
|
+
const message =
|
|
35
|
+
error instanceof Error ? error.message : String(error);
|
|
36
|
+
throw new Error(`Failed to read VC file "${vcFile}": ${message}`, {
|
|
37
|
+
cause: error,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const specOpt = opts["spec"];
|
|
43
|
+
if (specOpt !== undefined && specOpt !== "draft14" && specOpt !== "1.0") {
|
|
44
|
+
throw new Error('Invalid --spec value. Must be "draft14" or "1.0".');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const accessToken = await getAccessToken({
|
|
48
|
+
config,
|
|
49
|
+
scope,
|
|
50
|
+
wallet,
|
|
51
|
+
...(specOpt !== undefined && { spec: specOpt }),
|
|
52
|
+
...(vcJwt !== undefined && { vcJwt }),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Optionally persist the token
|
|
56
|
+
const save = Boolean(opts["save"]);
|
|
57
|
+
if (save) {
|
|
58
|
+
setPersistedConfigValue("token", accessToken);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
access_token: accessToken,
|
|
63
|
+
did: wallet.did,
|
|
64
|
+
saved: save,
|
|
65
|
+
scope,
|
|
66
|
+
signedWith: wallet.signingKey().alg,
|
|
67
|
+
};
|
|
68
|
+
},
|
|
69
|
+
id: "auth.token",
|
|
70
|
+
options: [
|
|
71
|
+
{
|
|
72
|
+
description:
|
|
73
|
+
"EBSI authorisation scope. Required. Either a single scope " +
|
|
74
|
+
'(e.g. "did-registry:write", "did-registry:invite"), or a space-separated combination of ' +
|
|
75
|
+
'write scopes for a multi-scope token (e.g. "did-registry:write issuers-registry:write"). ' +
|
|
76
|
+
"Only did-registry:write, issuers-registry:write, timestamp:write, track-and-trace:create, track-and-trace:write, policies-registry:write, " +
|
|
77
|
+
"and schemas-registry:write can be combined — invite/invoke scopes must be requested alone. " +
|
|
78
|
+
"Scopes that need a VC (did-registry:invite, ledger:invoke, issuers-registry:invite, track-and-trace:authorise) " +
|
|
79
|
+
"also require --vc and cannot be combined. Any scope may be suffixed with " +
|
|
80
|
+
'":<0x-address>" (e.g. "track-and-trace:write:0x61c36a8d610163660E21a8b7359e1Cac0C9133e1") ' +
|
|
81
|
+
"to target a specific deployed contract instance instead of the environment default.",
|
|
82
|
+
flags: "--scope <scope>",
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
description:
|
|
86
|
+
"Path to a VC JWT file. Required for invite/invoke scopes " +
|
|
87
|
+
"(did-registry:invite, ledger:invoke, issuers-registry:invite, track-and-trace:authorise).",
|
|
88
|
+
flags: "--vc <file>",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
description:
|
|
92
|
+
"Persist the obtained access token to config (equivalent to `ebsi config set token <jwt>`).",
|
|
93
|
+
flags: "--save",
|
|
94
|
+
},
|
|
95
|
+
...WALLET_KEY_OPTIONS,
|
|
96
|
+
{
|
|
97
|
+
description: "EBSI DID — overrides config/env.",
|
|
98
|
+
flags: "--did <did>",
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
description:
|
|
102
|
+
'Which OpenID4VP grant to speak: "draft14" (default, legacy Presentation ' +
|
|
103
|
+
'Exchange) or "1.0" (final, DCQL). Both are accepted by the Authorisation ' +
|
|
104
|
+
"service side by side.",
|
|
105
|
+
flags: "--spec <draft14|1.0>",
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
segments: ["auth", "token"],
|
|
109
|
+
summary:
|
|
110
|
+
"Obtain an EBSI access token via the OIDC4VP `vp_token` grant flow. " +
|
|
111
|
+
"Requires a configured secp256k1 key (--es256k-key, EBSI_ES256K_PRIVATE_KEY, " +
|
|
112
|
+
"or `ebsi config set es256kPrivateKey`); when a P-256 key is also configured, " +
|
|
113
|
+
"--sign-alg picks which one signs the VP. " +
|
|
114
|
+
'Pass several space-separated write scopes (e.g. --scope "did-registry:write issuers-registry:write") ' +
|
|
115
|
+
"to mint a single multi-scope token. " +
|
|
116
|
+
"Use --vc <file> for scopes that require a Verifiable Credential. " +
|
|
117
|
+
"Use --save to persist the token for subsequent commands.",
|
|
118
|
+
},
|
|
119
|
+
];
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import type { CommandDescriptor } from "./registry.ts";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
EBSI_ENVS,
|
|
5
|
+
getConfigFilePath,
|
|
6
|
+
getPersistedConfigValue,
|
|
7
|
+
OUTPUT_FORMATS,
|
|
8
|
+
setPersistedConfigValue,
|
|
9
|
+
SIGN_ALGS,
|
|
10
|
+
} from "../config/config.ts";
|
|
11
|
+
import { requiredArg } from "./shared/args.ts";
|
|
12
|
+
|
|
13
|
+
const SETTABLE_KEYS = [
|
|
14
|
+
"did",
|
|
15
|
+
"env",
|
|
16
|
+
"es256PrivateKey",
|
|
17
|
+
"es256kPrivateKey",
|
|
18
|
+
"output",
|
|
19
|
+
"signAlg",
|
|
20
|
+
"token",
|
|
21
|
+
] as const;
|
|
22
|
+
type SettableKey = (typeof SETTABLE_KEYS)[number];
|
|
23
|
+
|
|
24
|
+
export const configCommands: CommandDescriptor[] = [
|
|
25
|
+
{
|
|
26
|
+
args: [
|
|
27
|
+
{
|
|
28
|
+
description: `Config key to read (${SETTABLE_KEYS.join(", ")})`,
|
|
29
|
+
example: "env",
|
|
30
|
+
name: "key",
|
|
31
|
+
required: true,
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
group: "Config",
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
36
|
+
async handler(args) {
|
|
37
|
+
const key = args["key"] as SettableKey;
|
|
38
|
+
if (!SETTABLE_KEYS.includes(key)) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Unknown config key "${key}". Valid keys: ${SETTABLE_KEYS.join(", ")}`,
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
const value = getPersistedConfigValue(key);
|
|
44
|
+
return {
|
|
45
|
+
configFile: getConfigFilePath(),
|
|
46
|
+
key,
|
|
47
|
+
value: value ?? undefined,
|
|
48
|
+
};
|
|
49
|
+
},
|
|
50
|
+
id: "config.get",
|
|
51
|
+
options: [],
|
|
52
|
+
segments: ["config", "get"],
|
|
53
|
+
summary:
|
|
54
|
+
"Show the current persisted config value for a key " +
|
|
55
|
+
"(did, env, es256PrivateKey, es256kPrivateKey, output, signAlg, token)",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
args: [
|
|
59
|
+
{
|
|
60
|
+
description: `Config key (${SETTABLE_KEYS.join(", ")})`,
|
|
61
|
+
example: "env",
|
|
62
|
+
name: "key",
|
|
63
|
+
required: true,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
description: "Value to set",
|
|
67
|
+
example: "test",
|
|
68
|
+
name: "value",
|
|
69
|
+
required: true,
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
group: "Config",
|
|
73
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
74
|
+
async handler(args) {
|
|
75
|
+
const key = args["key"] as SettableKey;
|
|
76
|
+
|
|
77
|
+
if (!SETTABLE_KEYS.includes(key)) {
|
|
78
|
+
throw new Error(
|
|
79
|
+
`Unknown config key "${key}". Valid keys: ${SETTABLE_KEYS.join(", ")}`,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const value = requiredArg(args, "value");
|
|
84
|
+
|
|
85
|
+
// Validate values
|
|
86
|
+
if (
|
|
87
|
+
key === "env" &&
|
|
88
|
+
!EBSI_ENVS.includes(value as (typeof EBSI_ENVS)[number])
|
|
89
|
+
) {
|
|
90
|
+
throw new Error(
|
|
91
|
+
`Invalid env "${value}". Valid values: ${EBSI_ENVS.join(", ")}`,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
if (
|
|
95
|
+
key === "output" &&
|
|
96
|
+
!OUTPUT_FORMATS.includes(value as (typeof OUTPUT_FORMATS)[number])
|
|
97
|
+
) {
|
|
98
|
+
throw new Error(
|
|
99
|
+
`Invalid output "${value}". Valid values: ${OUTPUT_FORMATS.join(", ")}`,
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
if (
|
|
103
|
+
key === "signAlg" &&
|
|
104
|
+
!SIGN_ALGS.includes(value.toUpperCase() as (typeof SIGN_ALGS)[number])
|
|
105
|
+
) {
|
|
106
|
+
throw new Error(
|
|
107
|
+
`Invalid signAlg "${value}". Valid values: ${SIGN_ALGS.join(", ")}`,
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
setPersistedConfigValue(key, value);
|
|
112
|
+
return { configFile: getConfigFilePath(), key, value };
|
|
113
|
+
},
|
|
114
|
+
id: "config.set",
|
|
115
|
+
options: [],
|
|
116
|
+
segments: ["config", "set"],
|
|
117
|
+
summary:
|
|
118
|
+
"Persist a config value (key=did|env|es256PrivateKey|es256kPrivateKey|output|signAlg|token, " +
|
|
119
|
+
"value=...). WARNING: storing es256PrivateKey/es256kPrivateKey persists the key(s) as " +
|
|
120
|
+
"plaintext in the config file.",
|
|
121
|
+
},
|
|
122
|
+
];
|