@originator-profile/opvc 0.4.0-beta.1

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/README.md ADDED
@@ -0,0 +1,485 @@
1
+ # opvc - Originator Profile Verifiable Credential command line tool
2
+
3
+ Originator Profile (OP) 仕様に準拠した Verifiable Credential (VC) を作成・管理するためのツールです。
4
+
5
+ ## Installation
6
+
7
+ ### From source
8
+
9
+ ```sh
10
+ git clone https://github.com/originator-profile/profile-share.git
11
+ cd profile-share/packages/opvc
12
+ pnpm install
13
+ npm i -g .
14
+ opvc
15
+ ```
16
+
17
+ ### Using `npx` / `npm`
18
+
19
+ GitHub Packages にアクセスするため .npmrc 設定が必要です。
20
+
21
+ 1. GitHub の [Personal Access Token (classic)](https://github.com/settings/tokens) を発行
22
+ - 必要なスコープ:
23
+ - `read:packages`
24
+ - `repo`
25
+ 2. GitHub Packages のレジストリと認証トークンを設定
26
+
27
+ ```sh
28
+ npm config set @originator-profile:registry https://npm.pkg.github.com
29
+ npm config set //npm.pkg.github.com/:_authToken YOUR_PERSONAL_ACCESS_TOKEN
30
+ ```
31
+
32
+ ```sh
33
+ # npx
34
+ npx -y @originator-profile/opvc
35
+
36
+ # npm
37
+ npm i -g @originator-profile/opvc
38
+ opvc
39
+ ```
40
+
41
+ ## Commands
42
+
43
+ <!-- prettier-ignore-start -->
44
+ <!-- commands -->
45
+ * [`opvc ca:sign`](#opvc-casign)
46
+ * [`opvc ca:unsigned`](#opvc-caunsigned)
47
+ * [`opvc help [COMMAND]`](#opvc-help-command)
48
+ * [`opvc key-gen`](#opvc-key-gen)
49
+ * [`opvc sign`](#opvc-sign)
50
+ * [`opvc wsp:unsigned`](#opvc-wspunsigned)
51
+
52
+ ## `opvc ca:sign`
53
+
54
+ Content Attestation の作成
55
+
56
+ ```
57
+ USAGE
58
+ $ opvc ca:sign -i <value> --input <filepath> [--issued-at <value>] [--expired-at <value>]
59
+
60
+ FLAGS
61
+ -i, --identity=<value> (required) プライベート鍵のファイルパス
62
+ --expired-at=<value> 有効期限 (ISO 8601)
63
+ --input=<filepath> (required) 入力ファイルのパス (JSON 形式)
64
+ --issued-at=<value> 発行日時 (ISO 8601)
65
+
66
+ DESCRIPTION
67
+ Content Attestation の作成
68
+
69
+ 標準出力に Content Attestation を出力します。
70
+
71
+ EXAMPLES
72
+ $ opvc ca:sign \
73
+ -i account-key.example.priv.json \
74
+ --input article-content-attestation.example.json
75
+
76
+ FLAG DESCRIPTIONS
77
+ -i, --identity=<value> プライベート鍵のファイルパス
78
+
79
+ プライベート鍵のファイルパスを渡してください。プライベート鍵は JWK 形式か、PEM base64 でエンコードされた PKCS #8
80
+ 形式にしてください。
81
+
82
+ --expired-at=<value> 有効期限 (ISO 8601)
83
+
84
+ 日付のみの場合、その日の 24:00:00.000 より前まで有効、それ以外の場合、期限切れとなる日付・時刻・秒を指定します。
85
+
86
+ --input=<filepath> 入力ファイルのパス (JSON 形式)
87
+
88
+ Article Content Attestation の例:
89
+
90
+ {
91
+ "@context": [
92
+ "https://www.w3.org/ns/credentials/v2",
93
+ "https://originator-profile.org/ns/credentials/v1",
94
+ "https://originator-profile.org/ns/cip/v1",
95
+ {
96
+ "@language": "ja"
97
+ }
98
+ ],
99
+ "type": [
100
+ "VerifiableCredential",
101
+ "ContentAttestation"
102
+ ],
103
+ "issuer": "dns:example.com",
104
+ "credentialSubject": {
105
+ "id": "urn:uuid:78550fa7-f846-4e0f-ad5c-8d34461cb95b",
106
+ "type": "Article",
107
+ "headline": "<Webページのタイトル>",
108
+ "image": {
109
+ "id": "<サムネイル画像URL>",
110
+ "content": [
111
+ "<コンテンツ (data:// 形式URL)>"
112
+ ]
113
+ },
114
+ "description": "<Webページの説明>",
115
+ "author": [
116
+ "山田花子"
117
+ ],
118
+ "editor": [
119
+ "山田太郎"
120
+ ],
121
+ "datePublished": "2023-07-04T19:14:00Z",
122
+ "dateModified": "2023-07-04T19:14:00Z",
123
+ "genre": "Arts & Entertainment"
124
+ },
125
+ "allowedUrl": "https://media.example.com/articles/2024-06-30",
126
+ "target": [
127
+ {
128
+ "type": "<Target Integrityの種別>",
129
+ "content": [
130
+ "<コンテンツ本体 (text/html or URL)>"
131
+ ],
132
+ "cssSelector": "<CSS セレクター (optional)>"
133
+ }
134
+ ]
135
+ }
136
+ ```
137
+
138
+ ## `opvc ca:unsigned`
139
+
140
+ 未署名 Content Attestation の取得
141
+
142
+ ```
143
+ USAGE
144
+ $ opvc ca:unsigned --input <filepath> [--issued-at <value>] [--expired-at <value>]
145
+
146
+ FLAGS
147
+ --expired-at=<value> 有効期限 (ISO 8601)
148
+ --input=<filepath> (required) 入力ファイルのパス (JSON 形式)
149
+ --issued-at=<value> 発行日時 (ISO 8601)
150
+
151
+ DESCRIPTION
152
+ 未署名 Content Attestation の取得
153
+
154
+ 標準出力に未署名 Content Attestation を出力します。
155
+ target[].integrity を省略した場合、type に準じて content から integrity を計算します。
156
+ 一方、target[].integrity が含まれる場合、その値をそのまま使用します。
157
+ なお、いずれも target[].content プロパティが削除される点にご注意ください。
158
+ これにより入力ファイルの target[] と異なる結果が含まれますが、これは正しい動作です。
159
+
160
+ EXAMPLES
161
+ $ opvc ca:unsigned \
162
+ --input article-content-attestation.example.json
163
+
164
+ FLAG DESCRIPTIONS
165
+ --expired-at=<value> 有効期限 (ISO 8601)
166
+
167
+ 日付のみの場合、その日の 24:00:00.000 より前まで有効、それ以外の場合、期限切れとなる日付・時刻・秒を指定します。
168
+
169
+ --input=<filepath> 入力ファイルのパス (JSON 形式)
170
+
171
+ Article Content Attestation の例:
172
+
173
+ {
174
+ "@context": [
175
+ "https://www.w3.org/ns/credentials/v2",
176
+ "https://originator-profile.org/ns/credentials/v1",
177
+ "https://originator-profile.org/ns/cip/v1",
178
+ {
179
+ "@language": "<言語・地域コード>"
180
+ }
181
+ ],
182
+ "type": [
183
+ "VerifiableCredential",
184
+ "ContentAttestation"
185
+ ],
186
+ "issuer": "<OP ID>",
187
+ "credentialSubject": {
188
+ "id": "<CA ID>",
189
+ "type": "Article",
190
+ "headline": "<コンテンツのタイトル>",
191
+ "description": "<コンテンツの説明>",
192
+ "image": {
193
+ "id": "<サムネイル画像URL>",
194
+ "content": [
195
+ "<コンテンツ (data:// 形式URL)>"
196
+ ]
197
+ },
198
+ "datePublished": "<公開日時>",
199
+ "dateModified": "<最終更新日時>",
200
+ "author": [
201
+ "<著者名>"
202
+ ],
203
+ "editor": [
204
+ "<編集者名>"
205
+ ],
206
+ "genre": "<ジャンル>"
207
+ },
208
+ "allowedUrl": "<CAの使用を許可するWebページのURL Pattern>",
209
+ "target": [
210
+ {
211
+ "type": "<Target Integrityの種別>",
212
+ "content": [
213
+ "<コンテンツ本体 (text/html or URL)>"
214
+ ],
215
+ "cssSelector": "<CSS セレクター (optional)>"
216
+ }
217
+ ]
218
+ }
219
+ ```
220
+
221
+ ## `opvc help [COMMAND]`
222
+
223
+ Display help for opvc.
224
+
225
+ ```
226
+ USAGE
227
+ $ opvc help [COMMAND...] [-n]
228
+
229
+ ARGUMENTS
230
+ COMMAND... Command to show help for.
231
+
232
+ FLAGS
233
+ -n, --nested-commands Include all nested commands in the output.
234
+
235
+ DESCRIPTION
236
+ Display help for opvc.
237
+ ```
238
+
239
+ _See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.2.29/src/commands/help.ts)_
240
+
241
+ ## `opvc key-gen`
242
+
243
+ 鍵ペアの生成
244
+
245
+ ```
246
+ USAGE
247
+ $ opvc key-gen -o <value>
248
+
249
+ FLAGS
250
+ -o, --output=<value> (required) 鍵を保存するファイル名(拡張子除く)。<output>.priv.json と <output>.pub.json
251
+ を出力します。
252
+
253
+ DESCRIPTION
254
+ 鍵ペアの生成
255
+ ```
256
+
257
+ ## `opvc sign`
258
+
259
+ VC の作成
260
+
261
+ ```
262
+ USAGE
263
+ $ opvc sign -i <value> --input <filepath> [--id <value>] [--issued-at <value>] [--expired-at <value>]
264
+
265
+ FLAGS
266
+ -i, --identity=<value> (required) プライベート鍵のファイルパス
267
+ --expired-at=<value> 有効期限 (ISO 8601)
268
+ --id=<value> OP ID (ドメイン名)
269
+ --input=<filepath> (required) 入力ファイルのパス (JSON 形式)
270
+ --issued-at=<value> 発行日時 (ISO 8601)
271
+
272
+ DESCRIPTION
273
+ VC の作成
274
+
275
+ VC に署名します。
276
+ 標準出力に VC を出力します。
277
+
278
+ EXAMPLES
279
+ $ opvc sign \
280
+ -i example.priv.json \
281
+ --id example.com \
282
+ --input core-profile.json
283
+
284
+ $ opvc sign \
285
+ -i example.priv.json \
286
+ --id example.org \
287
+ --input web-media-profile.json
288
+
289
+ $ opvc sign \
290
+ -i account-key.example.priv.json \
291
+ --input website-profile.example.json
292
+
293
+ FLAG DESCRIPTIONS
294
+ -i, --identity=<value> プライベート鍵のファイルパス
295
+
296
+ プライベート鍵のファイルパスを渡してください。プライベート鍵は JWK 形式か、PEM base64 でエンコードされた PKCS #8
297
+ 形式にしてください。
298
+
299
+ --expired-at=<value> 有効期限 (ISO 8601)
300
+
301
+ 日付のみの場合、その日の 24:00:00.000 より前まで有効、それ以外の場合、期限切れとなる日付・時刻・秒を指定します。
302
+
303
+ --id=<value> OP ID (ドメイン名)
304
+
305
+ ドメイン名 (RFC 4501) を指定します。
306
+
307
+ --input=<filepath> 入力ファイルのパス (JSON 形式)
308
+
309
+ コアプロファイル (CP) の例:
310
+
311
+ {
312
+ "@context": [
313
+ "https://www.w3.org/ns/credentials/v2",
314
+ "https://originator-profile.org/ns/credentials/v1"
315
+ ],
316
+ "type": [
317
+ "VerifiableCredential",
318
+ "CoreProfile"
319
+ ],
320
+ "issuer": "dns:example.org",
321
+ "credentialSubject": {
322
+ "id": "dns:example.jp",
323
+ "type": "Core",
324
+ "jwks": {
325
+ "keys": [
326
+ {
327
+ "kid": "LIstkoCvByn4jk8oZPvigQkzTzO9UwnGnE-VMlkZvYQ",
328
+ "kty": "EC",
329
+ "crv": "P-256",
330
+ "x": "QiVI-I-3gv-17KN0RFLHKh5Vj71vc75eSOkyMsxFxbE",
331
+ "y": "bEzRDEy41bihcTnpSILImSVymTQl9BQZq36QpCpJQnI"
332
+ }
333
+ ]
334
+ }
335
+ }
336
+ }
337
+
338
+ ウェブメディアプロファイル (WMP) の例:
339
+
340
+ {
341
+ "@context": [
342
+ "https://www.w3.org/ns/credentials/v2",
343
+ "https://originator-profile.org/ns/credentials/v1",
344
+ "https://originator-profile.org/ns/cip/v1",
345
+ {
346
+ "@language": "ja"
347
+ }
348
+ ],
349
+ "type": [
350
+ "VerifiableCredential",
351
+ "WebMediaProfile"
352
+ ],
353
+ "issuer": "dns:wmp-issuer.example.org",
354
+ "credentialSubject": {
355
+ "id": "dns:wmp-holder.example.jp",
356
+ "type": "OnlineBusiness",
357
+ "url": "https://www.wmp-holder.example.jp/",
358
+ "name": "○○メディア (※開発用サンプル)",
359
+ "logo": {
360
+ "id": "https://www.wmp-holder.example.jp/image.png",
361
+ "digestSRI": "sha256-Upwn7gYMuRmJlD1ZivHk876vXHzokXrwXj50VgfnMnY="
362
+ },
363
+ "email": "contact@wmp-holder.example.jp",
364
+ "telephone": "0000000000",
365
+ "contactPoint": {
366
+ "id": "https://wmp-holder.example.jp/contact",
367
+ "name": "お問い合わせ"
368
+ },
369
+ "informationTransmissionPolicy": {
370
+ "id": "https://wmp-holder.example.jp/statement",
371
+ "name": "情報発信ポリシー"
372
+ },
373
+ "privacyPolicy": {
374
+ "id": "https://wmp-holder.example.jp/privacy",
375
+ "name": "プライバシーポリシー"
376
+ },
377
+ "description": "この文章はこの Web メディアに関する補足情報です。"
378
+ }
379
+ }
380
+
381
+ Website Profile (WSP) の例:
382
+
383
+ {
384
+ "@context": [
385
+ "https://www.w3.org/ns/credentials/v2",
386
+ "https://originator-profile.org/ns/credentials/v1",
387
+ "https://originator-profile.org/ns/cip/v1",
388
+ {
389
+ "@language": "ja"
390
+ }
391
+ ],
392
+ "type": [
393
+ "VerifiableCredential",
394
+ "WebsiteProfile"
395
+ ],
396
+ "issuer": "dns:example.com",
397
+ "credentialSubject": {
398
+ "id": "https://media.example.com/",
399
+ "type": "WebSite",
400
+ "name": "<Webサイトのタイトル>",
401
+ "description": "<Webサイトの説明>",
402
+ "image": {
403
+ "id": "https://media.example.com/image.png",
404
+ "digestSRI": "sha256-Upwn7gYMuRmJlD1ZivHk876vXHzokXrwXj50VgfnMnY="
405
+ },
406
+ "allowedOrigin": [
407
+ "https://media.example.com"
408
+ ]
409
+ }
410
+ }
411
+ ```
412
+
413
+ ## `opvc wsp:unsigned`
414
+
415
+ 未署名 Website Profile の取得
416
+
417
+ ```
418
+ USAGE
419
+ $ opvc wsp:unsigned --input <filepath> [--issued-at <value>] [--expired-at <value>]
420
+
421
+ FLAGS
422
+ --expired-at=<value> 有効期限 (ISO 8601)
423
+ --input=<filepath> (required) 入力ファイルのパス (JSON 形式)
424
+ --issued-at=<value> 発行日時 (ISO 8601)
425
+
426
+ DESCRIPTION
427
+ 未署名 Website Profile の取得
428
+
429
+ 標準出力に未署名 Website Profile を出力します。
430
+
431
+ EXAMPLES
432
+ $ opvc wsp:unsigned \
433
+ --input website-profile.example.json
434
+
435
+ FLAG DESCRIPTIONS
436
+ --expired-at=<value> 有効期限 (ISO 8601)
437
+
438
+ 日付のみの場合、その日の 24:00:00.000 より前まで有効、それ以外の場合、期限切れとなる日付・時刻・秒を指定します。
439
+
440
+ --input=<filepath> 入力ファイルのパス (JSON 形式)
441
+
442
+ Website Profile の例:
443
+
444
+ {
445
+ "@context": [
446
+ "https://www.w3.org/ns/credentials/v2",
447
+ "https://originator-profile.org/ns/credentials/v1",
448
+ "https://originator-profile.org/ns/cip/v1",
449
+ {
450
+ "@language": "<言語・地域コード>"
451
+ }
452
+ ],
453
+ "type": [
454
+ "VerifiableCredential",
455
+ "WebsiteProfile"
456
+ ],
457
+ "issuer": "<OP ID>",
458
+ "credentialSubject": {
459
+ "id": "<Web サイトのオリジン (形式: https://<ホスト名>)>",
460
+ "type": "WebSite",
461
+ "name": "<Web サイトの名称>",
462
+ "description": "<Web サイトの説明>",
463
+ "image": {
464
+ "id": "<サムネイル画像URL>",
465
+ "content": [
466
+ "<コンテンツ (data:// 形式URL)>"
467
+ ]
468
+ },
469
+ "allowedOrigin": [
470
+ "<Web サイトのオリジン (形式: https://<ホスト名>)>"
471
+ ]
472
+ }
473
+ }
474
+ ```
475
+ <!-- commandsstop -->
476
+ <!-- prettier-ignore-end -->
477
+
478
+ ## Development
479
+
480
+ ```sh
481
+ git clone https://github.com/originator-profile/profile-share.git
482
+ cd profile-share/packages/opvc
483
+ pnpm install
484
+ bin/dev.ts
485
+ ```
package/bin/dev.cmd ADDED
@@ -0,0 +1,3 @@
1
+ @echo off
2
+
3
+ node --experimental-strip-types --no-warnings=ExperimentalWarning "%~dp0\dev.ts" %*
package/bin/dev.ts ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env -S node --experimental-strip-types --disable-warning=ExperimentalWarning
2
+
3
+ import { execute } from "@oclif/core";
4
+
5
+ await execute({ development: true, dir: import.meta.url });
package/bin/run.cmd ADDED
@@ -0,0 +1,3 @@
1
+ @echo off
2
+
3
+ node "%~dp0\run.js" %*
package/bin/run.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { execute } from "@oclif/core";
4
+
5
+ await execute({ dir: import.meta.url });
@@ -0,0 +1,13 @@
1
+ //#region rolldown:runtime
2
+ var __defProp = Object.defineProperty;
3
+ var __export = (all) => {
4
+ let target = {};
5
+ for (var name in all) __defProp(target, name, {
6
+ get: all[name],
7
+ enumerable: true
8
+ });
9
+ return target;
10
+ };
11
+
12
+ //#endregion
13
+ export { __export as t };
@@ -0,0 +1,29 @@
1
+ import { Command } from "@oclif/core";
2
+ import * as _oclif_core_interfaces15 from "@oclif/core/interfaces";
3
+
4
+ //#region src/commands/ca/sign.d.ts
5
+ declare class CaSign extends Command {
6
+ static summary: string;
7
+ static description: string;
8
+ static flags: {
9
+ identity: _oclif_core_interfaces15.OptionFlag<{
10
+ [x: string]: unknown;
11
+ use?: string | undefined;
12
+ key_ops?: string[] | undefined;
13
+ alg?: string | undefined;
14
+ x5u?: string | undefined;
15
+ x5c?: string[] | undefined;
16
+ x5t?: string | undefined;
17
+ "x5t#S256"?: string | undefined;
18
+ kty: string;
19
+ kid: string;
20
+ }, _oclif_core_interfaces15.CustomOptions>;
21
+ input: _oclif_core_interfaces15.OptionFlag<string, _oclif_core_interfaces15.CustomOptions>;
22
+ "issued-at": _oclif_core_interfaces15.OptionFlag<string | undefined, _oclif_core_interfaces15.CustomOptions>;
23
+ "expired-at": _oclif_core_interfaces15.OptionFlag<Date | undefined, _oclif_core_interfaces15.CustomOptions>;
24
+ };
25
+ static examples: string[];
26
+ run(): Promise<void>;
27
+ }
28
+ //#endregion
29
+ export { CaSign };
@@ -0,0 +1,71 @@
1
+ import { n as sign } from "../../content-attestation-2NuarC85.js";
2
+ import { r as privateKey, t as expirationDate } from "../../flags-BuWTYwYw.js";
3
+ import { Command, Flags } from "@oclif/core";
4
+ import fs from "node:fs/promises";
5
+
6
+ //#region src/commands/ca/sign.ts
7
+ const exampleArticleContentAttestation = {
8
+ "@context": [
9
+ "https://www.w3.org/ns/credentials/v2",
10
+ "https://originator-profile.org/ns/credentials/v1",
11
+ "https://originator-profile.org/ns/cip/v1",
12
+ { "@language": "ja" }
13
+ ],
14
+ type: ["VerifiableCredential", "ContentAttestation"],
15
+ issuer: "dns:example.com",
16
+ credentialSubject: {
17
+ id: "urn:uuid:78550fa7-f846-4e0f-ad5c-8d34461cb95b",
18
+ type: "Article",
19
+ headline: "<Webページのタイトル>",
20
+ image: {
21
+ id: "<サムネイル画像URL>",
22
+ content: ["<コンテンツ (data:// 形式URL)>"]
23
+ },
24
+ description: "<Webページの説明>",
25
+ author: ["山田花子"],
26
+ editor: ["山田太郎"],
27
+ datePublished: "2023-07-04T19:14:00Z",
28
+ dateModified: "2023-07-04T19:14:00Z",
29
+ genre: "Arts & Entertainment"
30
+ },
31
+ allowedUrl: "https://media.example.com/articles/2024-06-30",
32
+ target: [{
33
+ type: "<Target Integrityの種別>",
34
+ content: ["<コンテンツ本体 (text/html or URL)>"],
35
+ cssSelector: "<CSS セレクター (optional)>"
36
+ }]
37
+ };
38
+ var CaSign = class CaSign extends Command {
39
+ static summary = "Content Attestation の作成";
40
+ static description = "標準出力に Content Attestation を出力します。";
41
+ static flags = {
42
+ identity: privateKey({ required: true }),
43
+ input: Flags.string({
44
+ summary: "入力ファイルのパス (JSON 形式)",
45
+ helpValue: "<filepath>",
46
+ description: `\
47
+ Article Content Attestation の例:
48
+
49
+ ${JSON.stringify(exampleArticleContentAttestation, null, " ")}`,
50
+ required: true
51
+ }),
52
+ "issued-at": Flags.string({ description: "発行日時 (ISO 8601)" }),
53
+ "expired-at": expirationDate()
54
+ };
55
+ static examples = [`\
56
+ $ <%= config.bin %> <%= command.id %> \\
57
+ -i account-key.example.priv.json \\
58
+ --input article-content-attestation.example.json`];
59
+ async run() {
60
+ const { flags } = await this.parse(CaSign);
61
+ const inputBuffer = await fs.readFile(flags.input);
62
+ const ca = await sign(JSON.parse(inputBuffer.toString()), flags.identity, {
63
+ issuedAt: flags["issued-at"],
64
+ expiredAt: flags["expired-at"]
65
+ });
66
+ this.log(ca);
67
+ }
68
+ };
69
+
70
+ //#endregion
71
+ export { CaSign };
@@ -0,0 +1,17 @@
1
+ import { Command } from "@oclif/core";
2
+ import * as _oclif_core_interfaces0 from "@oclif/core/interfaces";
3
+
4
+ //#region src/commands/ca/unsigned.d.ts
5
+ declare class CaUnsigned extends Command {
6
+ static summary: string;
7
+ static description: string;
8
+ static flags: {
9
+ input: _oclif_core_interfaces0.OptionFlag<string, _oclif_core_interfaces0.CustomOptions>;
10
+ "issued-at": _oclif_core_interfaces0.OptionFlag<string | undefined, _oclif_core_interfaces0.CustomOptions>;
11
+ "expired-at": _oclif_core_interfaces0.OptionFlag<Date | undefined, _oclif_core_interfaces0.CustomOptions>;
12
+ };
13
+ static examples: string[];
14
+ run(): Promise<void>;
15
+ }
16
+ //#endregion
17
+ export { CaUnsigned };
@@ -0,0 +1,74 @@
1
+ import { r as unsignedCa } from "../../content-attestation-2NuarC85.js";
2
+ import { t as expirationDate } from "../../flags-BuWTYwYw.js";
3
+ import { Command, Flags } from "@oclif/core";
4
+ import fs from "node:fs/promises";
5
+
6
+ //#region src/commands/ca/unsigned.ts
7
+ const exampleArticleContentAttestation = {
8
+ "@context": [
9
+ "https://www.w3.org/ns/credentials/v2",
10
+ "https://originator-profile.org/ns/credentials/v1",
11
+ "https://originator-profile.org/ns/cip/v1",
12
+ { "@language": "<言語・地域コード>" }
13
+ ],
14
+ type: ["VerifiableCredential", "ContentAttestation"],
15
+ issuer: "<OP ID>",
16
+ credentialSubject: {
17
+ id: "<CA ID>",
18
+ type: "Article",
19
+ headline: "<コンテンツのタイトル>",
20
+ description: "<コンテンツの説明>",
21
+ image: {
22
+ id: "<サムネイル画像URL>",
23
+ content: ["<コンテンツ (data:// 形式URL)>"]
24
+ },
25
+ datePublished: "<公開日時>",
26
+ dateModified: "<最終更新日時>",
27
+ author: ["<著者名>"],
28
+ editor: ["<編集者名>"],
29
+ genre: "<ジャンル>"
30
+ },
31
+ allowedUrl: "<CAの使用を許可するWebページのURL Pattern>",
32
+ target: [{
33
+ type: "<Target Integrityの種別>",
34
+ content: ["<コンテンツ本体 (text/html or URL)>"],
35
+ cssSelector: "<CSS セレクター (optional)>"
36
+ }]
37
+ };
38
+ var CaUnsigned = class CaUnsigned extends Command {
39
+ static summary = "未署名 Content Attestation の取得";
40
+ static description = `\
41
+ 標準出力に未署名 Content Attestation を出力します。
42
+ target[].integrity を省略した場合、type に準じて content から integrity を計算します。
43
+ 一方、target[].integrity が含まれる場合、その値をそのまま使用します。
44
+ なお、いずれも target[].content プロパティが削除される点にご注意ください。
45
+ これにより入力ファイルの target[] と異なる結果が含まれますが、これは正しい動作です。`;
46
+ static flags = {
47
+ input: Flags.string({
48
+ summary: "入力ファイルのパス (JSON 形式)",
49
+ helpValue: "<filepath>",
50
+ description: `\
51
+ Article Content Attestation の例:
52
+
53
+ ${JSON.stringify(exampleArticleContentAttestation, null, " ")}`,
54
+ required: true
55
+ }),
56
+ "issued-at": Flags.string({ description: "発行日時 (ISO 8601)" }),
57
+ "expired-at": expirationDate()
58
+ };
59
+ static examples = [`\
60
+ $ <%= config.bin %> <%= command.id %> \\
61
+ --input article-content-attestation.example.json`];
62
+ async run() {
63
+ const { flags } = await this.parse(CaUnsigned);
64
+ const inputBuffer = await fs.readFile(flags.input);
65
+ const uca = await unsignedCa(JSON.parse(inputBuffer.toString()), {
66
+ issuedAt: flags["issued-at"],
67
+ expiredAt: flags["expired-at"]
68
+ });
69
+ this.logJson(uca);
70
+ }
71
+ };
72
+
73
+ //#endregion
74
+ export { CaUnsigned };
@@ -0,0 +1,13 @@
1
+ import { Command } from "@oclif/core";
2
+ import * as _oclif_core_interfaces23 from "@oclif/core/interfaces";
3
+
4
+ //#region src/commands/key-gen/index.d.ts
5
+ declare class KeyGen extends Command {
6
+ static description: string;
7
+ static flags: {
8
+ output: _oclif_core_interfaces23.OptionFlag<string, _oclif_core_interfaces23.CustomOptions>;
9
+ };
10
+ run(): Promise<void>;
11
+ }
12
+ //#endregion
13
+ export { KeyGen };
@@ -0,0 +1,24 @@
1
+ import { Command, Flags } from "@oclif/core";
2
+ import fs from "node:fs/promises";
3
+ import { generateKey } from "@originator-profile/cryptography";
4
+
5
+ //#region src/commands/key-gen/index.ts
6
+ var KeyGen = class KeyGen extends Command {
7
+ static description = "鍵ペアの生成";
8
+ static flags = { output: Flags.string({
9
+ char: "o",
10
+ description: "鍵を保存するファイル名(拡張子除く)。<output>.priv.json と <output>.pub.json を出力します。",
11
+ required: true
12
+ }) };
13
+ async run() {
14
+ const { flags } = await this.parse(KeyGen);
15
+ const { publicKey, privateKey } = await generateKey();
16
+ const privateKeyFilename = `${flags.output}.priv.json`;
17
+ const publicKeyFilename = `${flags.output}.pub.json`;
18
+ await fs.writeFile(publicKeyFilename, JSON.stringify(publicKey, null, 2));
19
+ await fs.writeFile(privateKeyFilename, JSON.stringify(privateKey, null, 2));
20
+ }
21
+ };
22
+
23
+ //#endregion
24
+ export { KeyGen };
@@ -0,0 +1,30 @@
1
+ import { Command } from "@oclif/core";
2
+ import * as _oclif_core_interfaces5 from "@oclif/core/interfaces";
3
+
4
+ //#region src/commands/sign.d.ts
5
+ declare class VcSign extends Command {
6
+ static summary: string;
7
+ static description: string;
8
+ static flags: {
9
+ identity: _oclif_core_interfaces5.OptionFlag<{
10
+ [x: string]: unknown;
11
+ use?: string | undefined;
12
+ key_ops?: string[] | undefined;
13
+ alg?: string | undefined;
14
+ x5u?: string | undefined;
15
+ x5c?: string[] | undefined;
16
+ x5t?: string | undefined;
17
+ "x5t#S256"?: string | undefined;
18
+ kty: string;
19
+ kid: string;
20
+ }, _oclif_core_interfaces5.CustomOptions>;
21
+ id: _oclif_core_interfaces5.OptionFlag<string | undefined, _oclif_core_interfaces5.CustomOptions>;
22
+ input: _oclif_core_interfaces5.OptionFlag<string, _oclif_core_interfaces5.CustomOptions>;
23
+ "issued-at": _oclif_core_interfaces5.OptionFlag<string | undefined, _oclif_core_interfaces5.CustomOptions>;
24
+ "expired-at": _oclif_core_interfaces5.OptionFlag<Date | undefined, _oclif_core_interfaces5.CustomOptions>;
25
+ };
26
+ static examples: string[];
27
+ run(): Promise<void>;
28
+ }
29
+ //#endregion
30
+ export { VcSign };
@@ -0,0 +1,151 @@
1
+ import { n as opId, r as privateKey, t as expirationDate } from "../flags-BuWTYwYw.js";
2
+ import { fetchAndSetDigestSri } from "@originator-profile/sign";
3
+ import { addYears } from "date-fns";
4
+ import { Command, Flags } from "@oclif/core";
5
+ import { signJwtVc } from "@originator-profile/securing-mechanism";
6
+ import fs from "node:fs/promises";
7
+
8
+ //#region src/commands/sign.ts
9
+ function isValidVc(vc) {
10
+ return typeof vc === "object" && vc !== null && "credentialSubject" in vc && typeof vc.credentialSubject === "object" && vc.credentialSubject !== null;
11
+ }
12
+ async function addDigestSri(vc) {
13
+ if (!isValidVc(vc)) throw new Error("Invalid VC");
14
+ const credentialSubject = vc.credentialSubject;
15
+ await fetchAndSetDigestSri("sha256", credentialSubject.logo);
16
+ await fetchAndSetDigestSri("sha256", credentialSubject.image);
17
+ return Object.assign(vc, { credentialSubject });
18
+ }
19
+ const exampleCoreProfile = {
20
+ "@context": ["https://www.w3.org/ns/credentials/v2", "https://originator-profile.org/ns/credentials/v1"],
21
+ type: ["VerifiableCredential", "CoreProfile"],
22
+ issuer: "dns:example.org",
23
+ credentialSubject: {
24
+ id: "dns:example.jp",
25
+ type: "Core",
26
+ jwks: { keys: [{
27
+ kid: "LIstkoCvByn4jk8oZPvigQkzTzO9UwnGnE-VMlkZvYQ",
28
+ kty: "EC",
29
+ crv: "P-256",
30
+ x: "QiVI-I-3gv-17KN0RFLHKh5Vj71vc75eSOkyMsxFxbE",
31
+ y: "bEzRDEy41bihcTnpSILImSVymTQl9BQZq36QpCpJQnI"
32
+ }] }
33
+ }
34
+ };
35
+ const exampleWebMediaProfile = {
36
+ "@context": [
37
+ "https://www.w3.org/ns/credentials/v2",
38
+ "https://originator-profile.org/ns/credentials/v1",
39
+ "https://originator-profile.org/ns/cip/v1",
40
+ { "@language": "ja" }
41
+ ],
42
+ type: ["VerifiableCredential", "WebMediaProfile"],
43
+ issuer: "dns:wmp-issuer.example.org",
44
+ credentialSubject: {
45
+ id: "dns:wmp-holder.example.jp",
46
+ type: "OnlineBusiness",
47
+ url: "https://www.wmp-holder.example.jp/",
48
+ name: "○○メディア (※開発用サンプル)",
49
+ logo: {
50
+ id: "https://www.wmp-holder.example.jp/image.png",
51
+ digestSRI: "sha256-Upwn7gYMuRmJlD1ZivHk876vXHzokXrwXj50VgfnMnY="
52
+ },
53
+ email: "contact@wmp-holder.example.jp",
54
+ telephone: "0000000000",
55
+ contactPoint: {
56
+ id: "https://wmp-holder.example.jp/contact",
57
+ name: "お問い合わせ"
58
+ },
59
+ informationTransmissionPolicy: {
60
+ id: "https://wmp-holder.example.jp/statement",
61
+ name: "情報発信ポリシー"
62
+ },
63
+ privacyPolicy: {
64
+ id: "https://wmp-holder.example.jp/privacy",
65
+ name: "プライバシーポリシー"
66
+ },
67
+ description: "この文章はこの Web メディアに関する補足情報です。"
68
+ }
69
+ };
70
+ const exampleWebsiteProfile = {
71
+ "@context": [
72
+ "https://www.w3.org/ns/credentials/v2",
73
+ "https://originator-profile.org/ns/credentials/v1",
74
+ "https://originator-profile.org/ns/cip/v1",
75
+ { "@language": "ja" }
76
+ ],
77
+ type: ["VerifiableCredential", "WebsiteProfile"],
78
+ issuer: "dns:example.com",
79
+ credentialSubject: {
80
+ id: "https://media.example.com/",
81
+ type: "WebSite",
82
+ name: "<Webサイトのタイトル>",
83
+ description: "<Webサイトの説明>",
84
+ image: {
85
+ id: "https://media.example.com/image.png",
86
+ digestSRI: "sha256-Upwn7gYMuRmJlD1ZivHk876vXHzokXrwXj50VgfnMnY="
87
+ },
88
+ allowedOrigin: ["https://media.example.com"]
89
+ }
90
+ };
91
+ var VcSign = class VcSign extends Command {
92
+ static summary = "VC の作成";
93
+ static description = `\
94
+ VC に署名します。
95
+ 標準出力に VC を出力します。`;
96
+ static flags = {
97
+ identity: privateKey({ required: true }),
98
+ id: opId(),
99
+ input: Flags.string({
100
+ summary: "入力ファイルのパス (JSON 形式)",
101
+ helpValue: "<filepath>",
102
+ description: `\
103
+ コアプロファイル (CP) の例:
104
+
105
+ ${JSON.stringify(exampleCoreProfile, null, " ")}
106
+
107
+ ウェブメディアプロファイル (WMP) の例:
108
+
109
+ ${JSON.stringify(exampleWebMediaProfile, null, " ")}
110
+
111
+ Website Profile (WSP) の例:
112
+
113
+ ${JSON.stringify(exampleWebsiteProfile, null, " ")}`,
114
+ required: true
115
+ }),
116
+ "issued-at": Flags.string({ description: "発行日時 (ISO 8601)" }),
117
+ "expired-at": expirationDate()
118
+ };
119
+ static examples = [
120
+ `\
121
+ $ <%= config.bin %> <%= command.id %> \\
122
+ -i example.priv.json \\
123
+ --id example.com \\
124
+ --input core-profile.json`,
125
+ `\
126
+ $ <%= config.bin %> <%= command.id %> \\
127
+ -i example.priv.json \\
128
+ --id example.org \\
129
+ --input web-media-profile.json`,
130
+ `\
131
+ $ <%= config.bin %> <%= command.id %> \\
132
+ -i account-key.example.priv.json \\
133
+ --input website-profile.example.json`
134
+ ];
135
+ async run() {
136
+ const { flags } = await this.parse(VcSign);
137
+ const inputBuffer = await fs.readFile(flags.input);
138
+ const input = JSON.parse(inputBuffer.toString());
139
+ const issuedAt = new Date(flags["issued-at"] ?? Date.now());
140
+ const expiredAt = flags["expired-at"] ?? addYears(/* @__PURE__ */ new Date(), 1);
141
+ if (flags.id) input.credentialSubject.id = flags.id;
142
+ const vc = await signJwtVc(await addDigestSri(input), flags.identity, {
143
+ issuedAt,
144
+ expiredAt
145
+ });
146
+ this.log(vc);
147
+ }
148
+ };
149
+
150
+ //#endregion
151
+ export { VcSign };
@@ -0,0 +1,17 @@
1
+ import { Command } from "@oclif/core";
2
+ import * as _oclif_core_interfaces25 from "@oclif/core/interfaces";
3
+
4
+ //#region src/commands/wsp/unsigned.d.ts
5
+ declare class WspUnsigned extends Command {
6
+ static summary: string;
7
+ static description: string;
8
+ static flags: {
9
+ input: _oclif_core_interfaces25.OptionFlag<string, _oclif_core_interfaces25.CustomOptions>;
10
+ "issued-at": _oclif_core_interfaces25.OptionFlag<string | undefined, _oclif_core_interfaces25.CustomOptions>;
11
+ "expired-at": _oclif_core_interfaces25.OptionFlag<Date | undefined, _oclif_core_interfaces25.CustomOptions>;
12
+ };
13
+ static examples: string[];
14
+ run(): Promise<void>;
15
+ }
16
+ //#endregion
17
+ export { WspUnsigned };
@@ -0,0 +1,59 @@
1
+ import { t as unsignedWsp } from "../../website-profile-D43BL7p3.js";
2
+ import { t as expirationDate } from "../../flags-BuWTYwYw.js";
3
+ import { Command, Flags } from "@oclif/core";
4
+ import fs from "node:fs/promises";
5
+
6
+ //#region src/commands/wsp/unsigned.ts
7
+ const exampleWebsiteProfile = {
8
+ "@context": [
9
+ "https://www.w3.org/ns/credentials/v2",
10
+ "https://originator-profile.org/ns/credentials/v1",
11
+ "https://originator-profile.org/ns/cip/v1",
12
+ { "@language": "<言語・地域コード>" }
13
+ ],
14
+ type: ["VerifiableCredential", "WebsiteProfile"],
15
+ issuer: "<OP ID>",
16
+ credentialSubject: {
17
+ id: "<Web サイトのオリジン (形式: https://<ホスト名>)>",
18
+ type: "WebSite",
19
+ name: "<Web サイトの名称>",
20
+ description: "<Web サイトの説明>",
21
+ image: {
22
+ id: "<サムネイル画像URL>",
23
+ content: ["<コンテンツ (data:// 形式URL)>"]
24
+ },
25
+ allowedOrigin: ["<Web サイトのオリジン (形式: https://<ホスト名>)>"]
26
+ }
27
+ };
28
+ var WspUnsigned = class WspUnsigned extends Command {
29
+ static summary = "未署名 Website Profile の取得";
30
+ static description = "標準出力に未署名 Website Profile を出力します。";
31
+ static flags = {
32
+ input: Flags.string({
33
+ summary: "入力ファイルのパス (JSON 形式)",
34
+ helpValue: "<filepath>",
35
+ description: `\
36
+ Website Profile の例:
37
+
38
+ ${JSON.stringify(exampleWebsiteProfile, null, " ")}`,
39
+ required: true
40
+ }),
41
+ "issued-at": Flags.string({ description: "発行日時 (ISO 8601)" }),
42
+ "expired-at": expirationDate()
43
+ };
44
+ static examples = [`\
45
+ $ <%= config.bin %> <%= command.id %> \\
46
+ --input website-profile.example.json`];
47
+ async run() {
48
+ const { flags } = await this.parse(WspUnsigned);
49
+ const inputBuffer = await fs.readFile(flags.input);
50
+ const uwsp = await unsignedWsp(JSON.parse(inputBuffer.toString()), {
51
+ issuedAt: flags["issued-at"],
52
+ expiredAt: flags["expired-at"]
53
+ });
54
+ this.logJson(uwsp);
55
+ }
56
+ };
57
+
58
+ //#endregion
59
+ export { WspUnsigned };
@@ -0,0 +1,75 @@
1
+ import { t as __export } from "./chunk-Bp6m_JJh.js";
2
+ import { JSDOM } from "jsdom";
3
+ import { parseExpirationDate } from "@originator-profile/core";
4
+ import { fetchAndSetDigestSri, fetchAndSetTargetIntegrity, signCa } from "@originator-profile/sign";
5
+ import { addYears, getUnixTime } from "date-fns";
6
+ import { BadRequestError } from "http-errors-enhanced";
7
+
8
+ //#region src/document-provider.ts
9
+ async function documentProvider({ type, content = "" }) {
10
+ if (Array.isArray(content) && content.length > 1) throw new Error("Multiple contents are not supported in this context.");
11
+ [content] = [content].flat();
12
+ let url;
13
+ let html = "";
14
+ if (type === "ExternalResourceTargetIntegrity") {
15
+ url = URL.canParse(content) ? content : void 0;
16
+ html = "";
17
+ } else if (URL.canParse(content)) {
18
+ url = content;
19
+ html = await fetch(url).then((res) => res.text());
20
+ } else {
21
+ url = void 0;
22
+ html = content;
23
+ }
24
+ return new JSDOM(html, { url }).window.document;
25
+ }
26
+
27
+ //#endregion
28
+ //#region src/content-attestation.ts
29
+ var content_attestation_exports = /* @__PURE__ */ __export({
30
+ sign: () => sign,
31
+ unsignedCa: () => unsignedCa
32
+ });
33
+ /**
34
+ * Content Attestation への署名
35
+ * @param uca 未署名 Content Attestation オブジェクト
36
+ * @param privateKey プライベート鍵
37
+ * @return Content Attestation
38
+ */
39
+ async function sign(uca, privateKey, { issuedAt: issuedAtDateOrString = /* @__PURE__ */ new Date(), expiredAt: expiredAtDateOrString = addYears(/* @__PURE__ */ new Date(), 1) }) {
40
+ const issuedAt = new Date(issuedAtDateOrString);
41
+ const expiredAt = typeof expiredAtDateOrString === "string" ? parseExpirationDate(expiredAtDateOrString) : expiredAtDateOrString;
42
+ uca.credentialSubject.id ??= `urn:uuid:${crypto.randomUUID()}`;
43
+ return await signCa(uca, privateKey, {
44
+ issuedAt,
45
+ expiredAt,
46
+ documentProvider
47
+ });
48
+ }
49
+ /**
50
+ * 未署名 Content Attestation の取得
51
+ * @param uca 未署名 Content Attestation オブジェクト
52
+ * @throws {BadRequestError} 検証対象のコンテンツが存在しない/コンテンツにアクセスできない/Integrityの計算に失敗
53
+ * @return 未署名 Content Attestation オブジェクト
54
+ */
55
+ async function unsignedCa(uca, { issuedAt: issuedAtDateOrString = /* @__PURE__ */ new Date(), expiredAt: expiredAtDateOrString = addYears(/* @__PURE__ */ new Date(), 1) }) {
56
+ const issuedAt = new Date(issuedAtDateOrString);
57
+ const expiredAt = typeof expiredAtDateOrString === "string" ? parseExpirationDate(expiredAtDateOrString) : expiredAtDateOrString;
58
+ uca.credentialSubject.id ??= `urn:uuid:${crypto.randomUUID()}`;
59
+ try {
60
+ await fetchAndSetDigestSri("sha256", uca.credentialSubject.image);
61
+ await fetchAndSetTargetIntegrity("sha256", uca, documentProvider);
62
+ } catch (e) {
63
+ throw new BadRequestError(e.message);
64
+ }
65
+ return {
66
+ iss: uca.issuer,
67
+ sub: uca.credentialSubject.id,
68
+ iat: getUnixTime(issuedAt),
69
+ exp: getUnixTime(expiredAt),
70
+ ...uca
71
+ };
72
+ }
73
+
74
+ //#endregion
75
+ export { documentProvider as i, sign as n, unsignedCa as r, content_attestation_exports as t };
@@ -0,0 +1,38 @@
1
+ import { parseExpirationDate } from "@originator-profile/core";
2
+ import { Flags } from "@oclif/core";
3
+ import fs from "node:fs/promises";
4
+ import { exportJWK, importPKCS8 } from "jose";
5
+
6
+ //#region src/flags.ts
7
+ const opId = Flags.custom({
8
+ summary: "OP ID (ドメイン名)",
9
+ description: `\
10
+ ドメイン名 (RFC 4501) を指定します。`,
11
+ async parse(domainName) {
12
+ const id = domainName.toLowerCase();
13
+ return domainName.startsWith("dns:") ? id : `dns:${id}`;
14
+ }
15
+ });
16
+ const privateKey = Flags.custom({
17
+ char: "i",
18
+ summary: "プライベート鍵のファイルパス",
19
+ description: "プライベート鍵のファイルパスを渡してください。プライベート鍵は JWK 形式か、PEM base64 でエンコードされた PKCS #8 形式にしてください。",
20
+ async parse(filepath) {
21
+ const fileContent = (await fs.readFile(filepath)).toString();
22
+ try {
23
+ return await exportJWK(await importPKCS8(fileContent, "ES256", { extractable: true }));
24
+ } catch (e) {
25
+ return JSON.parse(fileContent);
26
+ }
27
+ }
28
+ });
29
+ const expirationDate = Flags.custom({
30
+ summary: "有効期限 (ISO 8601)",
31
+ description: "日付のみの場合、その日の 24:00:00.000 より前まで有効、それ以外の場合、期限切れとなる日付・時刻・秒を指定します。",
32
+ async parse(input) {
33
+ return parseExpirationDate(input);
34
+ }
35
+ });
36
+
37
+ //#endregion
38
+ export { opId as n, privateKey as r, expirationDate as t };
@@ -0,0 +1,48 @@
1
+ import { t as __export } from "./chunk-Bp6m_JJh.js";
2
+ import { Jwk, RawTarget, UnsignedContentAttestation, WebsiteProfile } from "@originator-profile/model";
3
+
4
+ //#region src/document-provider.d.ts
5
+ declare function documentProvider({
6
+ type,
7
+ content
8
+ }: RawTarget): Promise<Document>;
9
+ /**
10
+ * Content Attestation への署名
11
+ * @param uca 未署名 Content Attestation オブジェクト
12
+ * @param privateKey プライベート鍵
13
+ * @return Content Attestation
14
+ */
15
+ declare function sign(uca: UnsignedContentAttestation, privateKey: Jwk, {
16
+ issuedAt: issuedAtDateOrString,
17
+ expiredAt: expiredAtDateOrString
18
+ }: {
19
+ issuedAt?: Date | string;
20
+ expiredAt?: Date | string;
21
+ }): Promise<string>;
22
+ /**
23
+ * 未署名 Content Attestation の取得
24
+ * @param uca 未署名 Content Attestation オブジェクト
25
+ * @throws {BadRequestError} 検証対象のコンテンツが存在しない/コンテンツにアクセスできない/Integrityの計算に失敗
26
+ * @return 未署名 Content Attestation オブジェクト
27
+ */
28
+ declare function unsignedCa(uca: UnsignedContentAttestation, {
29
+ issuedAt: issuedAtDateOrString,
30
+ expiredAt: expiredAtDateOrString
31
+ }: {
32
+ issuedAt?: Date | string;
33
+ expiredAt?: Date | string;
34
+ }): Promise<UnsignedContentAttestation>;
35
+ /**
36
+ * 未署名 Website Profile の取得
37
+ * @param uwsp 未署名 Website Profile オブジェクト
38
+ * @return 未署名 Website Profile オブジェクト
39
+ */
40
+ declare function unsignedWsp(uwsp: WebsiteProfile, {
41
+ issuedAt: issuedAtDateOrString,
42
+ expiredAt: expiredAtDateOrString
43
+ }: {
44
+ issuedAt?: Date | string;
45
+ expiredAt?: Date | string;
46
+ }): Promise<WebsiteProfile>;
47
+ //#endregion
48
+ export { content_attestation_d_exports as ContentAttestation, website_profile_d_exports as WebsiteProfile, documentProvider };
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ import { i as documentProvider, t as content_attestation_exports } from "./content-attestation-2NuarC85.js";
2
+ import { n as website_profile_exports } from "./website-profile-D43BL7p3.js";
3
+
4
+ export { content_attestation_exports as ContentAttestation, website_profile_exports as WebsiteProfile, documentProvider };
@@ -0,0 +1,27 @@
1
+ import { t as __export } from "./chunk-Bp6m_JJh.js";
2
+ import { parseExpirationDate } from "@originator-profile/core";
3
+ import { fetchAndSetDigestSri } from "@originator-profile/sign";
4
+ import { addYears, getUnixTime } from "date-fns";
5
+
6
+ //#region src/website-profile.ts
7
+ var website_profile_exports = /* @__PURE__ */ __export({ unsignedWsp: () => unsignedWsp });
8
+ /**
9
+ * 未署名 Website Profile の取得
10
+ * @param uwsp 未署名 Website Profile オブジェクト
11
+ * @return 未署名 Website Profile オブジェクト
12
+ */
13
+ async function unsignedWsp(uwsp, { issuedAt: issuedAtDateOrString = /* @__PURE__ */ new Date(), expiredAt: expiredAtDateOrString = addYears(/* @__PURE__ */ new Date(), 1) }) {
14
+ const issuedAt = new Date(issuedAtDateOrString);
15
+ const expiredAt = typeof expiredAtDateOrString === "string" ? parseExpirationDate(expiredAtDateOrString) : expiredAtDateOrString;
16
+ await fetchAndSetDigestSri("sha256", uwsp.credentialSubject.image);
17
+ return {
18
+ iss: uwsp.issuer,
19
+ sub: uwsp.credentialSubject.id,
20
+ iat: getUnixTime(issuedAt),
21
+ exp: getUnixTime(expiredAt),
22
+ ...uwsp
23
+ };
24
+ }
25
+
26
+ //#endregion
27
+ export { website_profile_exports as n, unsignedWsp as t };
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@originator-profile/opvc",
3
+ "version": "0.4.0-beta.1",
4
+ "private": false,
5
+ "type": "module",
6
+ "files": [
7
+ "bin",
8
+ "dist"
9
+ ],
10
+ "bin": "bin/run.js",
11
+ "exports": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "oclif": {
16
+ "bin": "opvc",
17
+ "commands": "dist/commands",
18
+ "plugins": [
19
+ "@oclif/plugin-help"
20
+ ]
21
+ },
22
+ "dependencies": {
23
+ "@oclif/core": "^4.4.0",
24
+ "@oclif/plugin-help": "^6.2.29",
25
+ "date-fns": "^4.1.0",
26
+ "http-errors-enhanced": "^3.0.2",
27
+ "jose": "^6.0.11",
28
+ "jsdom": "^27.0.0",
29
+ "@originator-profile/core": "0.4.0-beta.1",
30
+ "@originator-profile/cryptography": "0.4.0-beta.1",
31
+ "@originator-profile/sign": "0.4.0-beta.1",
32
+ "@originator-profile/securing-mechanism": "0.4.0-beta.1",
33
+ "@originator-profile/model": "0.4.0-beta.1"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "^24.3.1",
37
+ "eslint": "^9.25.1",
38
+ "oclif": "^4.20.1",
39
+ "tsdown": "^0.15.0",
40
+ "typescript": "^5.8.3",
41
+ "@originator-profile/tsconfig": "0.4.0-beta.1",
42
+ "eslint-config-originator-profile": "0.4.0-beta.1"
43
+ },
44
+ "scripts": {
45
+ "build": "tsdown && oclif manifest && oclif readme",
46
+ "lint": "eslint --fix .",
47
+ "type-check": "tsc",
48
+ "test": "node --experimental-strip-types --no-warnings=ExperimentalWarning --test"
49
+ }
50
+ }