@jccdex/vc-vocabularies 0.1.1 → 0.1.2

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 CHANGED
@@ -8,85 +8,439 @@ VC 业务词汇表与签发 Profile,配合 [`@jccdex/did`](../did) 的 `issueV
8
8
  yarn add @jccdex/vc-vocabularies @jccdex/did
9
9
  ```
10
10
 
11
- ## 快速开始
11
+ ## 支持的 VC 类型
12
12
 
13
- 使用 Profile 组装签发描述符,再交给 DID SDK 签名:
13
+ | 常量 | 类型字符串 | 场景 |
14
+ |------|-----------|------|
15
+ | `VC_TYPES.NFT_OWNERSHIP` | `NFTOwnership` | 证明持有某个 NFT |
16
+ | `VC_TYPES.NFT_USAGE_AUTHORIZATION` | `NFTUsageAuthorization` | 授权他人使用 NFT |
17
+ | `VC_TYPES.PHONE_VERIFICATION` | `PhoneVerificationCredential` | 手机号实名验证 |
18
+ | `VC_TYPES.FILE_ACCESS_AUTHORIZATION` | `FileAccessAuthorization` | 授权访问 IPFS/IPNS 上的文件或目录 |
19
+
20
+ 品牌 ID:`"ccdao"`(`ccda.ooo`)、`"jdid"`(`jdid.cn`)。
21
+
22
+ ---
23
+
24
+ ## VC 签发示例
25
+
26
+ > 以下示例展示签发描述符(Descriptor)的组装方式。描述符传入 `@jccdex/did` 的 `issueVC()` 后完成签名,最终产出标准 W3C VC JSON。
27
+
28
+ ### 1. NFT 所有权(NFTOwnership)
29
+
30
+ 证明某个地址持有特定 NFT。
14
31
 
15
32
  ```typescript
16
33
  import { issueVC } from "@jccdex/did";
17
34
  import { buildNftOwnershipDescriptor } from "@jccdex/vc-vocabularies";
18
35
 
19
36
  const descriptor = buildNftOwnershipDescriptor(
20
- "ccdao", // 品牌:ccdao | jdid
37
+ "ccdao",
21
38
  {
22
39
  id: holderDid,
23
40
  owner: holderDid,
24
41
  chainId: 1,
42
+ contractAddress: "0xAbCd...", // EVM 链填 contractAddress
43
+ // tokenName: "TokenSymbol", // SWTC 链改用 tokenName + nftIssuer
44
+ // nftIssuer: "rXxx...",
25
45
  tokenId: "123",
26
- contractAddress: "0x...",
27
46
  standard: "ERC-721",
28
- status: "Active",
47
+ status: "Active"
29
48
  },
30
49
  {
31
50
  id: `${holderDid}#vc-1`,
32
- expirationDate: "2099-01-01T00:00:00.000Z",
51
+ expirationDate: "2099-01-01T00:00:00.000Z"
33
52
  }
34
53
  );
35
54
 
36
55
  const vcJSON = await issueVC(descriptor, { sign, keyDoc });
37
56
  ```
38
57
 
39
- `subject` 由调用方按业务填写;Profile 负责组装 `types` 与 `@context`,签名由 `@jccdex/did` 完成。
58
+ <details>
59
+ <summary>签发后的 VC JSON 结构</summary>
60
+
61
+ ```json
62
+ {
63
+ "@context": [
64
+ "https://www.w3.org/2018/credentials/v1",
65
+ {
66
+ "NFTOwnership": "https://ccda.ooo/vc/v1#NFTOwnership",
67
+ "version": "https://ccda.ooo/did/v1",
68
+ "chainId": "https://ccda.ooo/did/v1#chainId",
69
+ "contractAddress": "https://ccda.ooo/did/v1#contractAddress",
70
+ "tokenName": "https://ccda.ooo/did/v1#tokenName",
71
+ "tokenId": "https://ccda.ooo/did/v1#tokenId",
72
+ "owner": "https://ccda.ooo/did/v1#owner",
73
+ "nftIssuer": "https://ccda.ooo/did/v1#nftIssuer",
74
+ "standard": "https://ccda.ooo/did/v1#standard",
75
+ "status": "https://ccda.ooo/did/v1#status"
76
+ }
77
+ ],
78
+ "type": ["VerifiableCredential", "NFTOwnership"],
79
+ "id": "did:ethr:0x1234...#vc-1",
80
+ "issuer": "did:ethr:0x1234...",
81
+ "issuanceDate": "2026-06-23T00:00:00Z",
82
+ "expirationDate": "2099-01-01T00:00:00Z",
83
+ "credentialSubject": {
84
+ "id": "did:ethr:0x1234...",
85
+ "owner": "did:ethr:0x1234...",
86
+ "chainId": 1,
87
+ "contractAddress": "0xAbCd...",
88
+ "tokenId": "123",
89
+ "standard": "ERC-721",
90
+ "status": "Active"
91
+ }
92
+ }
93
+ ```
94
+
95
+ </details>
96
+
97
+ ---
98
+
99
+ ### 2. NFT 使用授权(NFTUsageAuthorization)
100
+
101
+ 所有者授权他人在指定范围内使用 NFT(如商业用途、衍生作品等)。
102
+
103
+ ```typescript
104
+ import { buildNftUsageAuthorizationDescriptor } from "@jccdex/vc-vocabularies";
105
+
106
+ const descriptor = buildNftUsageAuthorizationDescriptor(
107
+ "ccdao",
108
+ {
109
+ id: granteeDid,
110
+ grantee: granteeDid,
111
+ owner: ownerDid,
112
+ chainId: 1,
113
+ contractAddress: "0xAbCd...",
114
+ tokenId: "123",
115
+ standard: "ERC-721",
116
+ status: "Active",
117
+ usageRights: "exclusive",
118
+ restrictions: {
119
+ commercial: true,
120
+ derivative: false,
121
+ sublicense: false,
122
+ territories: ["CN", "US"],
123
+ platforms: ["web", "mobile"]
124
+ }
125
+ },
126
+ {
127
+ id: `${ownerDid}#vc-auth-1`,
128
+ expirationDate: "2027-01-01T00:00:00.000Z"
129
+ }
130
+ );
131
+ ```
132
+
133
+ <details>
134
+ <summary>签发后的 VC JSON 结构</summary>
135
+
136
+ ```json
137
+ {
138
+ "@context": [
139
+ "https://www.w3.org/2018/credentials/v1",
140
+ {
141
+ "NFTUsageAuthorization": "https://ccda.ooo/vc/v1#NFTUsageAuthorization",
142
+ "version": "https://ccda.ooo/did/v1",
143
+ "grantee": "https://ccda.ooo/vc/v1#grantee",
144
+ "usageRights": "https://ccda.ooo/vc/v1#usageRights",
145
+ "restrictions": {
146
+ "@id": "https://ccda.ooo/vc/v1#restrictions",
147
+ "@context": {
148
+ "commercial": "https://ccda.ooo/vc/v1#commercial",
149
+ "derivative": "https://ccda.ooo/vc/v1#derivative",
150
+ "sublicense": "https://ccda.ooo/vc/v1#sublicense",
151
+ "territories": "https://ccda.ooo/vc/v1#territories",
152
+ "platforms": "https://ccda.ooo/vc/v1#platforms"
153
+ }
154
+ },
155
+ "chainId": "https://ccda.ooo/did/v1#chainId",
156
+ "contractAddress": "https://ccda.ooo/did/v1#contractAddress",
157
+ "tokenId": "https://ccda.ooo/did/v1#tokenId",
158
+ "owner": "https://ccda.ooo/did/v1#owner",
159
+ "standard": "https://ccda.ooo/did/v1#standard",
160
+ "status": "https://ccda.ooo/did/v1#status"
161
+ }
162
+ ],
163
+ "type": ["VerifiableCredential", "NFTUsageAuthorization"],
164
+ "id": "did:ethr:0x1234...#vc-auth-1",
165
+ "issuer": "did:ethr:0x1234...",
166
+ "issuanceDate": "2026-06-23T00:00:00Z",
167
+ "expirationDate": "2027-01-01T00:00:00Z",
168
+ "credentialSubject": {
169
+ "id": "did:ethr:0xABCD...",
170
+ "grantee": "did:ethr:0xABCD...",
171
+ "owner": "did:ethr:0x1234...",
172
+ "chainId": 1,
173
+ "contractAddress": "0xAbCd...",
174
+ "tokenId": "123",
175
+ "standard": "ERC-721",
176
+ "status": "Active",
177
+ "usageRights": "exclusive",
178
+ "restrictions": {
179
+ "commercial": true,
180
+ "derivative": false,
181
+ "sublicense": false,
182
+ "territories": ["CN", "US"],
183
+ "platforms": ["web", "mobile"]
184
+ }
185
+ }
186
+ }
187
+ ```
188
+
189
+ </details>
190
+
191
+ ---
192
+
193
+ ### 3. 电话验证(PhoneVerificationCredential)
194
+
195
+ 证明某个 DID 完成了手机号实名验证。
196
+
197
+ ```typescript
198
+ import { buildPhoneVerificationDescriptor } from "@jccdex/vc-vocabularies";
199
+
200
+ const descriptor = buildPhoneVerificationDescriptor(
201
+ "jdid",
202
+ {
203
+ id: userDid,
204
+ standard: "1.0",
205
+ status: "active",
206
+ verificationMethod: "sms-otp",
207
+ verificationProcess: {
208
+ verifiedAt: "2026-06-23T06:00:00Z",
209
+ updateAt: "2026-06-23T06:00:00Z",
210
+ verifierId: "did:ethr:0xVERIFIER..."
211
+ }
212
+ },
213
+ {
214
+ id: `${userDid}#vc-phone-1`,
215
+ expirationDate: "2027-06-23T00:00:00.000Z"
216
+ }
217
+ );
218
+ ```
219
+
220
+ <details>
221
+ <summary>签发后的 VC JSON 结构</summary>
222
+
223
+ ```json
224
+ {
225
+ "@context": [
226
+ "https://www.w3.org/2018/credentials/v1",
227
+ {
228
+ "PhoneVerificationCredential": "https://jdid.cn/vc/v1#PhoneVerificationCredential",
229
+ "version": "https://jdid.cn/did/v1",
230
+ "standard": "https://jdid.cn/did/v1#standard",
231
+ "status": "https://jdid.cn/did/v1#status",
232
+ "verificationMethod": "https://jdid.cn/did/v1#verificationMethod",
233
+ "verificationProcess": {
234
+ "@id": "https://jdid.cn/did/v1#verificationProcess",
235
+ "@context": {
236
+ "verifiedAt": "https://jdid.cn/did/v1#verifiedAt",
237
+ "updateAt": "https://jdid.cn/did/v1#updateAt",
238
+ "verifierId": "https://jdid.cn/did/v1#verifierId"
239
+ }
240
+ }
241
+ }
242
+ ],
243
+ "type": ["VerifiableCredential", "PhoneVerificationCredential"],
244
+ "id": "did:ethr:0xUSER...#vc-phone-1",
245
+ "issuer": "did:ethr:0xVERIFIER...",
246
+ "issuanceDate": "2026-06-23T06:00:00Z",
247
+ "expirationDate": "2027-06-23T00:00:00Z",
248
+ "credentialSubject": {
249
+ "id": "did:ethr:0xUSER...",
250
+ "standard": "1.0",
251
+ "status": "active",
252
+ "verificationMethod": "sms-otp",
253
+ "verificationProcess": {
254
+ "verifiedAt": "2026-06-23T06:00:00Z",
255
+ "updateAt": "2026-06-23T06:00:00Z",
256
+ "verifierId": "did:ethr:0xVERIFIER..."
257
+ }
258
+ }
259
+ }
260
+ ```
261
+
262
+ </details>
263
+
264
+ ---
265
+
266
+ ### 4. 文件访问授权(FileAccessAuthorization)
267
+
268
+ 基于 IPFS/IPNS 存储模型,授权他人访问链上文件或目录。
269
+
270
+ **设计说明:**
271
+ - `ipnsName`:IPNS 固定入口,所有者更新文件后入口不变,被授权方始终可通过它访问最新内容。
272
+ - 不存 CID:CID 随文件更新而变化;IPFS 内容寻址协议在取回内容时自动验证完整性,无需在 VC 层声明。
273
+ - `resourceType`:区分授权粒度为单文件(`"file"`)或目录(`"directory"`)。
274
+ - `resourcePath`:目录授权时可指定子路径,为空则整个 IPNS 目录均可访问。
275
+
276
+ ```typescript
277
+ import { buildFileAccessAuthorizationDescriptor } from "@jccdex/vc-vocabularies";
278
+
279
+ const descriptor = buildFileAccessAuthorizationDescriptor(
280
+ "ccdao",
281
+ {
282
+ id: granteeDid,
283
+ grantee: granteeDid,
284
+ ipnsName: "k51qzi5uqu5dh9ihj4g2s7qopkrpwhvy49rlcdmqbcg58k8q8z32lkj7k8s",
285
+ resourceType: "directory",
286
+ resourcePath: "/reports/2026", // 省略则整个目录
287
+ owner: ownerDid,
288
+ accessRights: ["read", "download"],
289
+ accessRestrictions: {
290
+ expiresAt: "2027-06-23T00:00:00.000Z",
291
+ maxDownloads: 50, // 0 = 不限次数
292
+ ipWhitelist: [] // 空 = 不限 IP
293
+ },
294
+ standard: "1.0",
295
+ status: "active"
296
+ },
297
+ {
298
+ id: `${ownerDid}#vc-file-1`,
299
+ expirationDate: "2027-06-23T00:00:00.000Z"
300
+ }
301
+ );
302
+ ```
303
+
304
+ <details>
305
+ <summary>签发后的 VC JSON 结构</summary>
306
+
307
+ ```json
308
+ {
309
+ "@context": [
310
+ "https://www.w3.org/2018/credentials/v1",
311
+ {
312
+ "FileAccessAuthorization": "https://ccda.ooo/vc/v1#FileAccessAuthorization",
313
+ "version": "https://ccda.ooo/did/v1",
314
+ "grantee": "https://ccda.ooo/vc/v1#grantee",
315
+ "accessRights": "https://ccda.ooo/vc/v1#accessRights",
316
+ "accessRestrictions": {
317
+ "@id": "https://ccda.ooo/vc/v1#accessRestrictions",
318
+ "@context": {
319
+ "expiresAt": "https://ccda.ooo/vc/v1#expiresAt",
320
+ "maxDownloads": "https://ccda.ooo/vc/v1#maxDownloads",
321
+ "ipWhitelist": "https://ccda.ooo/vc/v1#ipWhitelist"
322
+ }
323
+ },
324
+ "ipnsName": "https://ccda.ooo/did/v1#ipnsName",
325
+ "resourceType": "https://ccda.ooo/did/v1#resourceType",
326
+ "resourcePath": "https://ccda.ooo/did/v1#resourcePath",
327
+ "owner": "https://ccda.ooo/did/v1#owner",
328
+ "standard": "https://ccda.ooo/did/v1#standard",
329
+ "status": "https://ccda.ooo/did/v1#status"
330
+ }
331
+ ],
332
+ "type": ["VerifiableCredential", "FileAccessAuthorization"],
333
+ "id": "did:ethr:0x1234...#vc-file-1",
334
+ "issuer": "did:ethr:0x1234...",
335
+ "issuanceDate": "2026-06-23T06:34:00Z",
336
+ "expirationDate": "2027-06-23T00:00:00Z",
337
+ "credentialSubject": {
338
+ "id": "did:ethr:0xABCD...",
339
+ "grantee": "did:ethr:0xABCD...",
340
+ "ipnsName": "k51qzi5uqu5dh9ihj4g2s7qopkrpwhvy49rlcdmqbcg58k8q8z32lkj7k8s",
341
+ "resourceType": "directory",
342
+ "resourcePath": "/reports/2026",
343
+ "owner": "did:ethr:0x1234...",
344
+ "accessRights": ["read", "download"],
345
+ "accessRestrictions": {
346
+ "expiresAt": "2027-06-23T00:00:00Z",
347
+ "maxDownloads": 50,
348
+ "ipWhitelist": []
349
+ },
350
+ "standard": "1.0",
351
+ "status": "active"
352
+ }
353
+ }
354
+ ```
355
+
356
+ </details>
357
+
358
+ **被授权方访问流程:**
359
+
360
+ ```
361
+ 1. 持 VC 向资源服务方出示,服务方验证签名
362
+ 2. 从 credentialSubject.ipnsName 解析当前 CID(IPNS 查询)
363
+ 3. 按 resourcePath 限定可访问范围
364
+ 4. 从 IPFS 取内容,协议层自动以 CID 验证完整性(内容寻址天然自验证)
365
+ 5. 检查 accessRestrictions(到期时间、下载次数、IP 白名单)
366
+ ```
367
+
368
+ ---
40
369
 
41
370
  ## 主要 API
42
371
 
43
372
  | 导出 | 说明 |
44
373
  |------|------|
45
- | `buildNftOwnershipDescriptor` | NFT 所有权 VC |
46
- | `buildNftUsageAuthorizationDescriptor` | NFT 授权 VC |
47
- | `buildPhoneVerificationDescriptor` | 电话验证 VC |
374
+ | `buildNftOwnershipDescriptor` | NFT 所有权 VC 签发 Profile |
375
+ | `buildNftUsageAuthorizationDescriptor` | NFT 使用授权 VC 签发 Profile |
376
+ | `buildPhoneVerificationDescriptor` | 电话验证 VC 签发 Profile |
377
+ | `buildFileAccessAuthorizationDescriptor` | 文件访问授权 VC 签发 Profile |
48
378
  | `buildInlineContext` | 按字段生成最小内联 `@context` |
49
379
  | `VC_TYPES` | VC 业务类型常量 |
50
- | `getNftOwnershipContext` 等 | 按品牌获取内联 context 对象 |
380
+ | `getNftOwnershipContext` 等 | 按品牌获取完整内联 context 对象 |
381
+ | `CCDAO_*_CONTEXT` / `JDID_*_CONTEXT` | 各类型品牌具名 context 常量 |
51
382
 
52
- 品牌 ID:`"ccdao"`(`ccda.ooo`)、`"jdid"`(`jdid.cn`)。
383
+ ---
53
384
 
54
385
  ## 自定义 Descriptor
55
386
 
56
- 不经过 Profile 时,可自行组装后调用 `issueVC`:
387
+ 不经过 Profile 时,可用 `buildInlineContext` 按需裁剪字段,减小 VC 体积:
57
388
 
58
389
  ```typescript
59
390
  import {
60
391
  buildInlineContext,
61
392
  VC_TYPES,
62
- W3C_VC_CONTEXT_URL,
393
+ W3C_VC_CONTEXT_URL
63
394
  } from "@jccdex/vc-vocabularies";
64
395
 
396
+ // 仅携带本次 subject 用到的字段,忽略 contractAddress 等未用术语
65
397
  const descriptor = {
66
398
  types: [VC_TYPES.NFT_OWNERSHIP],
67
399
  contexts: [
68
400
  W3C_VC_CONTEXT_URL,
69
401
  buildInlineContext("jdid", {
70
402
  types: ["NFTOwnership"],
71
- fields: ["chainId", "tokenId", "tokenName", "nftIssuer", "owner", "standard", "status"],
72
- }),
403
+ fields: ["chainId", "tokenId", "tokenName", "nftIssuer", "owner", "standard", "status"]
404
+ })
73
405
  ],
74
406
  subject: { id: holderDid, /* ... */ },
75
407
  id: `${holderDid}#vc-1`,
76
- expirationDate: "2099-01-01T00:00:00.000Z",
408
+ expirationDate: "2099-01-01T00:00:00.000Z"
409
+ };
410
+
411
+ // 文件授权最小 context(仅携带访问必需字段)
412
+ const fileDescriptor = {
413
+ types: [VC_TYPES.FILE_ACCESS_AUTHORIZATION],
414
+ contexts: [
415
+ W3C_VC_CONTEXT_URL,
416
+ buildInlineContext("ccdao", {
417
+ types: ["FileAccessAuthorization"],
418
+ fields: ["ipnsName", "resourceType", "resourcePath", "accessRights", "accessRestrictions"]
419
+ })
420
+ ],
421
+ subject: { id: granteeDid, /* ... */ },
422
+ id: `${ownerDid}#vc-file-2`,
423
+ expirationDate: "2027-01-01T00:00:00.000Z"
77
424
  };
78
425
  ```
79
426
 
427
+ ---
428
+
80
429
  ## 词汇表 JSON(高级)
81
430
 
82
431
  验签缓存与品牌服务器部署使用 `contexts/*.json`,可通过子路径引用:
83
432
 
84
433
  ```javascript
85
- import jdidDidV1 from "@jccdex/vc-vocabularies/contexts/jdid-did-v1.json";
434
+ import ccdaoDidV1 from "@jccdex/vc-vocabularies/contexts/ccda-did-v1.json";
435
+ import jdidDidV1 from "@jccdex/vc-vocabularies/contexts/jdid-did-v1.json";
436
+ import ccdaoVcV1 from "@jccdex/vc-vocabularies/contexts/ccda-vc-v1.json";
437
+ import jdidVcV1 from "@jccdex/vc-vocabularies/contexts/jdid-vc-v1.json";
86
438
  ```
87
439
 
88
440
  一般由 `@jccdex/did` 内部引用,应用层通常无需直接 import。
89
441
 
442
+ ---
443
+
90
444
  ## 开发
91
445
 
92
446
  ```bash
package/lib/index.d.ts CHANGED
@@ -12,9 +12,11 @@ export * from "./vc-types.js";
12
12
  export { buildNftOwnershipDescriptor } from "./profiles/nft-ownership.js";
13
13
  export { buildNftUsageAuthorizationDescriptor } from "./profiles/nft-usage-authorization.js";
14
14
  export { buildPhoneVerificationDescriptor } from "./profiles/phone-verification.js";
15
+ export { buildFileAccessAuthorizationDescriptor } from "./profiles/file-access-authorization.js";
15
16
  import { buildNftOwnershipDescriptor } from "./profiles/nft-ownership.js";
16
17
  import { buildNftUsageAuthorizationDescriptor } from "./profiles/nft-usage-authorization.js";
17
18
  import { buildPhoneVerificationDescriptor } from "./profiles/phone-verification.js";
19
+ import { buildFileAccessAuthorizationDescriptor } from "./profiles/file-access-authorization.js";
18
20
  /** 按业务场景索引的 Profile 注册表,便于 DApp 动态选择签发模板 */
19
21
  export declare const profiles: {
20
22
  nftOwnership: {
@@ -26,4 +28,7 @@ export declare const profiles: {
26
28
  phoneVerification: {
27
29
  buildDescriptor: typeof buildPhoneVerificationDescriptor;
28
30
  };
31
+ fileAccessAuthorization: {
32
+ buildDescriptor: typeof buildFileAccessAuthorizationDescriptor;
33
+ };
29
34
  };
package/lib/index.js CHANGED
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.profiles = exports.buildPhoneVerificationDescriptor = exports.buildNftUsageAuthorizationDescriptor = exports.buildNftOwnershipDescriptor = void 0;
17
+ exports.profiles = exports.buildFileAccessAuthorizationDescriptor = exports.buildPhoneVerificationDescriptor = exports.buildNftUsageAuthorizationDescriptor = exports.buildNftOwnershipDescriptor = void 0;
18
18
  /**
19
19
  * @jccdex/vc-vocabularies 包入口。
20
20
  *
@@ -32,14 +32,20 @@ var nft_usage_authorization_js_1 = require("./profiles/nft-usage-authorization.j
32
32
  Object.defineProperty(exports, "buildNftUsageAuthorizationDescriptor", { enumerable: true, get: function () { return nft_usage_authorization_js_1.buildNftUsageAuthorizationDescriptor; } });
33
33
  var phone_verification_js_1 = require("./profiles/phone-verification.js");
34
34
  Object.defineProperty(exports, "buildPhoneVerificationDescriptor", { enumerable: true, get: function () { return phone_verification_js_1.buildPhoneVerificationDescriptor; } });
35
+ var file_access_authorization_js_1 = require("./profiles/file-access-authorization.js");
36
+ Object.defineProperty(exports, "buildFileAccessAuthorizationDescriptor", { enumerable: true, get: function () { return file_access_authorization_js_1.buildFileAccessAuthorizationDescriptor; } });
35
37
  const nft_ownership_js_2 = require("./profiles/nft-ownership.js");
36
38
  const nft_usage_authorization_js_2 = require("./profiles/nft-usage-authorization.js");
37
39
  const phone_verification_js_2 = require("./profiles/phone-verification.js");
40
+ const file_access_authorization_js_2 = require("./profiles/file-access-authorization.js");
38
41
  /** 按业务场景索引的 Profile 注册表,便于 DApp 动态选择签发模板 */
39
42
  exports.profiles = {
40
43
  nftOwnership: { buildDescriptor: nft_ownership_js_2.buildNftOwnershipDescriptor },
41
44
  nftUsageAuthorization: {
42
45
  buildDescriptor: nft_usage_authorization_js_2.buildNftUsageAuthorizationDescriptor
43
46
  },
44
- phoneVerification: { buildDescriptor: phone_verification_js_2.buildPhoneVerificationDescriptor }
47
+ phoneVerification: { buildDescriptor: phone_verification_js_2.buildPhoneVerificationDescriptor },
48
+ fileAccessAuthorization: {
49
+ buildDescriptor: file_access_authorization_js_2.buildFileAccessAuthorizationDescriptor
50
+ }
45
51
  };
@@ -1,15 +1,30 @@
1
1
  /**
2
2
  * 品牌内联 context 定义。
3
3
  *
4
- * 品牌(ccdao / jdid)仅区分国内外词汇表 URL 命名空间,术语字段集相同。
5
- * 链差异(EVM contractAddress、SWTC tokenName/nftIssuer)由应用层 subject 决定,
6
- * 不在词汇层按品牌或链裁剪。
4
+ * ## 设计原则
5
+ * - 品牌(ccdao / jdid)仅区分国内外词汇表 URL 命名空间,术语字段集相同。
6
+ * - 链差异(EVM 用 contractAddress、SWTC 用 tokenName/nftIssuer)由应用层 subject 决定,
7
+ * 不在词汇层按品牌或链裁剪。
8
+ * - 维护原则:只增不删、不改 URI(append-only)。
7
9
  *
8
- * 维护原则:只增不删、不改 URI(append-only)。
10
+ * ## 命名空间规则
11
+ * - `did#` 前缀:跨 VC 类型通用的实体属性(owner、status、chainId 等)
12
+ * - `vc#` 前缀:业务专属术语(grantee、usageRights、accessRights 等)
9
13
  */
10
14
  import type { BrandId } from "./types.js";
15
+ /** W3C Verifiable Credentials 标准 context URL,固定作为 @context 数组第一项 */
11
16
  export declare const W3C_VC_CONTEXT_URL = "https://www.w3.org/2018/credentials/v1";
12
- /** 统一 NFTOwnership 术语集,品牌只替换 URL 前缀 */
17
+ /**
18
+ * 构建 NFT 所有权 VC 的内联 @context 术语集。
19
+ *
20
+ * 链差异(EVM / SWTC)体现在 subject 字段选择上:
21
+ * - EVM:填 `contractAddress`
22
+ * - SWTC:填 `tokenName` + `nftIssuer`
23
+ * 词汇层两者均声明,由 DApp 按链选填。
24
+ *
25
+ * @param brand - 品牌 ID,决定 URL 命名空间
26
+ * @returns 内联 @context 对象,可直接放入 VC 的 `@context` 数组
27
+ */
13
28
  export declare function buildNftOwnershipContext(brand: BrandId): {
14
29
  NFTOwnership: string;
15
30
  version: "https://ccda.ooo/did/v1" | "https://jdid.cn/did/v1";
@@ -22,7 +37,15 @@ export declare function buildNftOwnershipContext(brand: BrandId): {
22
37
  standard: string;
23
38
  status: string;
24
39
  };
25
- /** 统一 NFTUsageAuthorization 术语集 */
40
+ /**
41
+ * 构建 NFT 使用授权 VC 的内联 @context 术语集。
42
+ *
43
+ * `restrictions` 是嵌套 context 对象,其子字段(commercial、derivative 等)
44
+ * 仅在该嵌套对象内有效,不与外层字段命名冲突。
45
+ *
46
+ * @param brand - 品牌 ID,决定 URL 命名空间
47
+ * @returns 内联 @context 对象,含嵌套 restrictions 术语集
48
+ */
26
49
  export declare function buildNftUsageAuthorizationContext(brand: BrandId): {
27
50
  NFTUsageAuthorization: string;
28
51
  version: "https://ccda.ooo/did/v1" | "https://jdid.cn/did/v1";
@@ -47,12 +70,27 @@ export declare function buildNftUsageAuthorizationContext(brand: BrandId): {
47
70
  standard: string;
48
71
  status: string;
49
72
  };
50
- /** DID 文档 version 内联 context */
73
+ /**
74
+ * 构建 DID 文档 version 字段的内联 @context。
75
+ *
76
+ * 仅包含 `version`(命名空间根 URL)与 `credentials` 两个术语,
77
+ * 用于 DID 文档自身,不是 VC subject 字段。
78
+ *
79
+ * @param brand - 品牌 ID,决定 URL 命名空间
80
+ * @returns 含 version / credentials 的最小 context 对象
81
+ */
51
82
  export declare function buildVersionContext(brand: BrandId): {
52
83
  version: "https://ccda.ooo/did/v1" | "https://jdid.cn/did/v1";
53
84
  credentials: string;
54
85
  };
55
- /** 电话验证 VC 术语集(两品牌结构相同,仅 URL 不同) */
86
+ /**
87
+ * 构建电话验证 VC 的内联 @context 术语集。
88
+ *
89
+ * `verificationProcess` 是嵌套 context,记录验证操作的时间、操作方等审计信息。
90
+ *
91
+ * @param brand - 品牌 ID,决定 URL 命名空间
92
+ * @returns 内联 @context 对象,含嵌套 verificationProcess 术语集
93
+ */
56
94
  export declare function buildPhoneVerificationContext(brand: BrandId): {
57
95
  PhoneVerificationCredential: string;
58
96
  version: "https://ccda.ooo/did/v1" | "https://jdid.cn/did/v1";
@@ -68,11 +106,54 @@ export declare function buildPhoneVerificationContext(brand: BrandId): {
68
106
  };
69
107
  };
70
108
  };
71
- /** 便捷 getter,供 DApp / Profile 使用 */
109
+ /**
110
+ * 构建文件访问授权 VC 的内联 @context 术语集(基于 IPFS/IPNS 存储模型)。
111
+ *
112
+ * ## 字段设计说明
113
+ *
114
+ * | 字段 | 命名空间 | 说明 |
115
+ * |----------------|----------|------------------------------------------------------------|
116
+ * | ipnsName | did# | IPNS 固定入口,所有者更新文件后仍指向同一名称 |
117
+ * | resourceType | did# | 授权粒度:"file" \| "directory" |
118
+ * | resourcePath | did# | 目录授权时的子路径限制,为空则整个 IPNS 目录均可访问 |
119
+ * | grantee | vc# | 被授权方 DID |
120
+ * | accessRights | vc# | 权限列表,如 ["read", "download"] |
121
+ * | accessRestrictions | vc# | 访问限制(嵌套对象):到期时间、最大下载次数、IP 白名单 |
122
+ *
123
+ * ## 为何不存 CID
124
+ * CID 随文件更新而变化,存入 VC 后会立即过时;
125
+ * 内容完整性由 IPFS 内容寻址协议层自动保证(取回内容时重算 CID 对比),
126
+ * 无需在凭证层额外声明。
127
+ *
128
+ * @param brand - 品牌 ID,决定 URL 命名空间
129
+ * @returns 内联 @context 对象,含嵌套 accessRestrictions 术语集
130
+ */
131
+ export declare function buildFileAccessAuthorizationContext(brand: BrandId): {
132
+ FileAccessAuthorization: string;
133
+ version: "https://ccda.ooo/did/v1" | "https://jdid.cn/did/v1";
134
+ grantee: string;
135
+ accessRights: string;
136
+ accessRestrictions: {
137
+ "@id": string;
138
+ "@context": {
139
+ expiresAt: string;
140
+ maxDownloads: string;
141
+ ipWhitelist: string;
142
+ };
143
+ };
144
+ ipnsName: string;
145
+ resourceType: string;
146
+ resourcePath: string;
147
+ owner: string;
148
+ standard: string;
149
+ status: string;
150
+ };
151
+ /** 便捷 getter 别名,供 DApp / Profile 使用(与 build* 函数等价) */
72
152
  export declare const getNftOwnershipContext: typeof buildNftOwnershipContext;
73
153
  export declare const getNftUsageAuthorizationContext: typeof buildNftUsageAuthorizationContext;
74
154
  export declare const getVersionContext: typeof buildVersionContext;
75
155
  export declare const getPhoneVerificationContext: typeof buildPhoneVerificationContext;
156
+ export declare const getFileAccessAuthorizationContext: typeof buildFileAccessAuthorizationContext;
76
157
  /** 向后兼容的具名导出(结构已统一,仅 URL 命名空间不同) */
77
158
  export declare const CCDAO_NFT_OWNERSHIP_CONTEXT: {
78
159
  NFTOwnership: string;
@@ -184,14 +265,70 @@ export declare const JDID_PHONE_VERIFICATION_CONTEXT: {
184
265
  };
185
266
  };
186
267
  };
268
+ export declare const CCDAO_FILE_ACCESS_AUTHORIZATION_CONTEXT: {
269
+ FileAccessAuthorization: string;
270
+ version: "https://ccda.ooo/did/v1" | "https://jdid.cn/did/v1";
271
+ grantee: string;
272
+ accessRights: string;
273
+ accessRestrictions: {
274
+ "@id": string;
275
+ "@context": {
276
+ expiresAt: string;
277
+ maxDownloads: string;
278
+ ipWhitelist: string;
279
+ };
280
+ };
281
+ ipnsName: string;
282
+ resourceType: string;
283
+ resourcePath: string;
284
+ owner: string;
285
+ standard: string;
286
+ status: string;
287
+ };
288
+ export declare const JDID_FILE_ACCESS_AUTHORIZATION_CONTEXT: {
289
+ FileAccessAuthorization: string;
290
+ version: "https://ccda.ooo/did/v1" | "https://jdid.cn/did/v1";
291
+ grantee: string;
292
+ accessRights: string;
293
+ accessRestrictions: {
294
+ "@id": string;
295
+ "@context": {
296
+ expiresAt: string;
297
+ maxDownloads: string;
298
+ ipWhitelist: string;
299
+ };
300
+ };
301
+ ipnsName: string;
302
+ resourceType: string;
303
+ resourcePath: string;
304
+ owner: string;
305
+ standard: string;
306
+ status: string;
307
+ };
187
308
  /**
188
309
  * 按本次签发需要的字段,生成最小内联 @context 对象。
189
310
  *
311
+ * 相较于直接使用 `buildXxxContext`(返回全量术语),此函数只保留
312
+ * 本次 subject 实际用到的字段,减小 VC 体积。
313
+ *
314
+ * 自动保留:
315
+ * - 类型标识符(opts.types 中的每一项,如 "NFTOwnership")
316
+ * - `version`(命名空间声明,始终需要)
317
+ *
318
+ * @param brand - 品牌 ID,决定 URL 命名空间
319
+ * @param opts.types - VC 类型名数组,如 ["NFTOwnership"]
320
+ * @param opts.fields - 需要解释的字段名;不传则返回该类型完整预设
321
+ *
190
322
  * @example
191
323
  * // 仅解释 tokenId、owner,不会带上 contractAddress
192
324
  * buildInlineContext("ccdao", { types: ["NFTOwnership"], fields: ["tokenId", "owner"] })
193
325
  *
194
- * 未传 fields 时返回该类型的完整预设(与 Profile 行为一致)。
326
+ * @example
327
+ * // 目录授权,只携带访问地址与权限字段
328
+ * buildInlineContext("jdid", {
329
+ * types: ["FileAccessAuthorization"],
330
+ * fields: ["ipnsName", "resourceType", "resourcePath", "accessRights"]
331
+ * })
195
332
  */
196
333
  export declare function buildInlineContext(brand: BrandId, opts: {
197
334
  types: string[];
@@ -1,22 +1,35 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.JDID_PHONE_VERIFICATION_CONTEXT = exports.CCDAO_PHONE_VERIFICATION_CONTEXT = exports.JDID_VERSION_CONTEXT = exports.CCDAO_VERSION_CONTEXT = exports.JDID_NFT_USAGE_AUTHORIZATION_CONTEXT = exports.CCDAO_NFT_USAGE_AUTHORIZATION_CONTEXT = exports.JDID_NFT_OWNERSHIP_CONTEXT = exports.CCDAO_NFT_OWNERSHIP_CONTEXT = exports.getPhoneVerificationContext = exports.getVersionContext = exports.getNftUsageAuthorizationContext = exports.getNftOwnershipContext = exports.W3C_VC_CONTEXT_URL = void 0;
3
+ exports.JDID_FILE_ACCESS_AUTHORIZATION_CONTEXT = exports.CCDAO_FILE_ACCESS_AUTHORIZATION_CONTEXT = exports.JDID_PHONE_VERIFICATION_CONTEXT = exports.CCDAO_PHONE_VERIFICATION_CONTEXT = exports.JDID_VERSION_CONTEXT = exports.CCDAO_VERSION_CONTEXT = exports.JDID_NFT_USAGE_AUTHORIZATION_CONTEXT = exports.CCDAO_NFT_USAGE_AUTHORIZATION_CONTEXT = exports.JDID_NFT_OWNERSHIP_CONTEXT = exports.CCDAO_NFT_OWNERSHIP_CONTEXT = exports.getFileAccessAuthorizationContext = exports.getPhoneVerificationContext = exports.getVersionContext = exports.getNftUsageAuthorizationContext = exports.getNftOwnershipContext = exports.W3C_VC_CONTEXT_URL = void 0;
4
4
  exports.buildNftOwnershipContext = buildNftOwnershipContext;
5
5
  exports.buildNftUsageAuthorizationContext = buildNftUsageAuthorizationContext;
6
6
  exports.buildVersionContext = buildVersionContext;
7
7
  exports.buildPhoneVerificationContext = buildPhoneVerificationContext;
8
+ exports.buildFileAccessAuthorizationContext = buildFileAccessAuthorizationContext;
8
9
  exports.buildInlineContext = buildInlineContext;
9
10
  const ccdao_js_1 = require("./brands/ccdao.js");
10
11
  const jdid_js_1 = require("./brands/jdid.js");
12
+ /** W3C Verifiable Credentials 标准 context URL,固定作为 @context 数组第一项 */
11
13
  exports.W3C_VC_CONTEXT_URL = "https://www.w3.org/2018/credentials/v1";
12
14
  const BRAND_URLS = {
13
15
  ccdao: { did: ccdao_js_1.CCDAO_DID_VOCAB_URL, vc: ccdao_js_1.CCDAO_VC_VOCAB_URL },
14
16
  jdid: { did: jdid_js_1.JDID_DID_VOCAB_URL, vc: jdid_js_1.JDID_VC_VOCAB_URL }
15
17
  };
18
+ /** 根据品牌取词汇表 URL 前缀 */
16
19
  function vocab(brand) {
17
20
  return BRAND_URLS[brand];
18
21
  }
19
- /** 统一 NFTOwnership 术语集,品牌只替换 URL 前缀 */
22
+ /**
23
+ * 构建 NFT 所有权 VC 的内联 @context 术语集。
24
+ *
25
+ * 链差异(EVM / SWTC)体现在 subject 字段选择上:
26
+ * - EVM:填 `contractAddress`
27
+ * - SWTC:填 `tokenName` + `nftIssuer`
28
+ * 词汇层两者均声明,由 DApp 按链选填。
29
+ *
30
+ * @param brand - 品牌 ID,决定 URL 命名空间
31
+ * @returns 内联 @context 对象,可直接放入 VC 的 `@context` 数组
32
+ */
20
33
  function buildNftOwnershipContext(brand) {
21
34
  const { did, vc } = vocab(brand);
22
35
  return {
@@ -32,7 +45,15 @@ function buildNftOwnershipContext(brand) {
32
45
  status: `${did}#status`
33
46
  };
34
47
  }
35
- /** 统一 NFTUsageAuthorization 术语集 */
48
+ /**
49
+ * 构建 NFT 使用授权 VC 的内联 @context 术语集。
50
+ *
51
+ * `restrictions` 是嵌套 context 对象,其子字段(commercial、derivative 等)
52
+ * 仅在该嵌套对象内有效,不与外层字段命名冲突。
53
+ *
54
+ * @param brand - 品牌 ID,决定 URL 命名空间
55
+ * @returns 内联 @context 对象,含嵌套 restrictions 术语集
56
+ */
36
57
  function buildNftUsageAuthorizationContext(brand) {
37
58
  const { did, vc } = vocab(brand);
38
59
  return {
@@ -60,7 +81,15 @@ function buildNftUsageAuthorizationContext(brand) {
60
81
  status: `${did}#status`
61
82
  };
62
83
  }
63
- /** DID 文档 version 内联 context */
84
+ /**
85
+ * 构建 DID 文档 version 字段的内联 @context。
86
+ *
87
+ * 仅包含 `version`(命名空间根 URL)与 `credentials` 两个术语,
88
+ * 用于 DID 文档自身,不是 VC subject 字段。
89
+ *
90
+ * @param brand - 品牌 ID,决定 URL 命名空间
91
+ * @returns 含 version / credentials 的最小 context 对象
92
+ */
64
93
  function buildVersionContext(brand) {
65
94
  const { did } = vocab(brand);
66
95
  return {
@@ -68,7 +97,14 @@ function buildVersionContext(brand) {
68
97
  credentials: `${did}#credentials`
69
98
  };
70
99
  }
71
- /** 电话验证 VC 术语集(两品牌结构相同,仅 URL 不同) */
100
+ /**
101
+ * 构建电话验证 VC 的内联 @context 术语集。
102
+ *
103
+ * `verificationProcess` 是嵌套 context,记录验证操作的时间、操作方等审计信息。
104
+ *
105
+ * @param brand - 品牌 ID,决定 URL 命名空间
106
+ * @returns 内联 @context 对象,含嵌套 verificationProcess 术语集
107
+ */
72
108
  function buildPhoneVerificationContext(brand) {
73
109
  const { did, vc } = vocab(brand);
74
110
  return {
@@ -87,11 +123,57 @@ function buildPhoneVerificationContext(brand) {
87
123
  }
88
124
  };
89
125
  }
90
- /** 便捷 getter,供 DApp / Profile 使用 */
126
+ /**
127
+ * 构建文件访问授权 VC 的内联 @context 术语集(基于 IPFS/IPNS 存储模型)。
128
+ *
129
+ * ## 字段设计说明
130
+ *
131
+ * | 字段 | 命名空间 | 说明 |
132
+ * |----------------|----------|------------------------------------------------------------|
133
+ * | ipnsName | did# | IPNS 固定入口,所有者更新文件后仍指向同一名称 |
134
+ * | resourceType | did# | 授权粒度:"file" \| "directory" |
135
+ * | resourcePath | did# | 目录授权时的子路径限制,为空则整个 IPNS 目录均可访问 |
136
+ * | grantee | vc# | 被授权方 DID |
137
+ * | accessRights | vc# | 权限列表,如 ["read", "download"] |
138
+ * | accessRestrictions | vc# | 访问限制(嵌套对象):到期时间、最大下载次数、IP 白名单 |
139
+ *
140
+ * ## 为何不存 CID
141
+ * CID 随文件更新而变化,存入 VC 后会立即过时;
142
+ * 内容完整性由 IPFS 内容寻址协议层自动保证(取回内容时重算 CID 对比),
143
+ * 无需在凭证层额外声明。
144
+ *
145
+ * @param brand - 品牌 ID,决定 URL 命名空间
146
+ * @returns 内联 @context 对象,含嵌套 accessRestrictions 术语集
147
+ */
148
+ function buildFileAccessAuthorizationContext(brand) {
149
+ const { did, vc } = vocab(brand);
150
+ return {
151
+ FileAccessAuthorization: `${vc}#FileAccessAuthorization`,
152
+ version: did,
153
+ grantee: `${vc}#grantee`,
154
+ accessRights: `${vc}#accessRights`,
155
+ accessRestrictions: {
156
+ "@id": `${vc}#accessRestrictions`,
157
+ "@context": {
158
+ expiresAt: `${vc}#expiresAt`,
159
+ maxDownloads: `${vc}#maxDownloads`,
160
+ ipWhitelist: `${vc}#ipWhitelist`
161
+ }
162
+ },
163
+ ipnsName: `${did}#ipnsName`,
164
+ resourceType: `${did}#resourceType`,
165
+ resourcePath: `${did}#resourcePath`,
166
+ owner: `${did}#owner`,
167
+ standard: `${did}#standard`,
168
+ status: `${did}#status`
169
+ };
170
+ }
171
+ /** 便捷 getter 别名,供 DApp / Profile 使用(与 build* 函数等价) */
91
172
  exports.getNftOwnershipContext = buildNftOwnershipContext;
92
173
  exports.getNftUsageAuthorizationContext = buildNftUsageAuthorizationContext;
93
174
  exports.getVersionContext = buildVersionContext;
94
175
  exports.getPhoneVerificationContext = buildPhoneVerificationContext;
176
+ exports.getFileAccessAuthorizationContext = buildFileAccessAuthorizationContext;
95
177
  /** 向后兼容的具名导出(结构已统一,仅 URL 命名空间不同) */
96
178
  exports.CCDAO_NFT_OWNERSHIP_CONTEXT = buildNftOwnershipContext("ccdao");
97
179
  exports.JDID_NFT_OWNERSHIP_CONTEXT = buildNftOwnershipContext("jdid");
@@ -101,12 +183,22 @@ exports.CCDAO_VERSION_CONTEXT = buildVersionContext("ccdao");
101
183
  exports.JDID_VERSION_CONTEXT = buildVersionContext("jdid");
102
184
  exports.CCDAO_PHONE_VERIFICATION_CONTEXT = buildPhoneVerificationContext("ccdao");
103
185
  exports.JDID_PHONE_VERIFICATION_CONTEXT = buildPhoneVerificationContext("jdid");
186
+ exports.CCDAO_FILE_ACCESS_AUTHORIZATION_CONTEXT = buildFileAccessAuthorizationContext("ccdao");
187
+ exports.JDID_FILE_ACCESS_AUTHORIZATION_CONTEXT = buildFileAccessAuthorizationContext("jdid");
188
+ /**
189
+ * 按 VC 类型名索引 context builder,供 `buildInlineContext` 内部使用。
190
+ * 新增 VC 类型时在此注册即可,无需修改 buildInlineContext 逻辑。
191
+ */
104
192
  const VC_TYPE_BUILDERS = {
105
193
  NFTOwnership: buildNftOwnershipContext,
106
194
  NFTUsageAuthorization: buildNftUsageAuthorizationContext,
107
- PhoneVerificationCredential: buildPhoneVerificationContext
195
+ PhoneVerificationCredential: buildPhoneVerificationContext,
196
+ FileAccessAuthorization: buildFileAccessAuthorizationContext
108
197
  };
109
- /** 从完整词汇表中仅取出 fields 列出的键,用于「最小内联 context」 */
198
+ /**
199
+ * 从完整词汇表中仅取出 fields 列出的键,用于构建「最小内联 context」。
200
+ * 自动保留类型标识符(type term)和 version,其余字段按需裁剪。
201
+ */
110
202
  function pickFields(source, fields) {
111
203
  const result = {};
112
204
  for (const field of fields) {
@@ -119,11 +211,27 @@ function pickFields(source, fields) {
119
211
  /**
120
212
  * 按本次签发需要的字段,生成最小内联 @context 对象。
121
213
  *
214
+ * 相较于直接使用 `buildXxxContext`(返回全量术语),此函数只保留
215
+ * 本次 subject 实际用到的字段,减小 VC 体积。
216
+ *
217
+ * 自动保留:
218
+ * - 类型标识符(opts.types 中的每一项,如 "NFTOwnership")
219
+ * - `version`(命名空间声明,始终需要)
220
+ *
221
+ * @param brand - 品牌 ID,决定 URL 命名空间
222
+ * @param opts.types - VC 类型名数组,如 ["NFTOwnership"]
223
+ * @param opts.fields - 需要解释的字段名;不传则返回该类型完整预设
224
+ *
122
225
  * @example
123
226
  * // 仅解释 tokenId、owner,不会带上 contractAddress
124
227
  * buildInlineContext("ccdao", { types: ["NFTOwnership"], fields: ["tokenId", "owner"] })
125
228
  *
126
- * 未传 fields 时返回该类型的完整预设(与 Profile 行为一致)。
229
+ * @example
230
+ * // 目录授权,只携带访问地址与权限字段
231
+ * buildInlineContext("jdid", {
232
+ * types: ["FileAccessAuthorization"],
233
+ * fields: ["ipnsName", "resourceType", "resourcePath", "accessRights"]
234
+ * })
127
235
  */
128
236
  function buildInlineContext(brand, opts) {
129
237
  const merged = {};
@@ -0,0 +1,23 @@
1
+ import type { BrandId, DescriptorMeta, VCIssuanceDescriptor } from "../types.js";
2
+ /**
3
+ * 构建文件访问授权 VC 签发描述符(基于 IPFS/IPNS 存储模型)。
4
+ *
5
+ * 两品牌词汇结构相同,仅 URL 命名空间不同。
6
+ *
7
+ * @param brand - 品牌 ID:"ccdao" | "jdid"
8
+ * @param subject - credentialSubject,必须包含 `id`(被授权方 DID)及以下业务字段:
9
+ * - `ipnsName` IPNS 固定入口(被授权方用来访问文件/目录的稳定地址)
10
+ * - `resourceType` 授权粒度:"file" | "directory"
11
+ * - `resourcePath` (可选)目录内子路径,为空则整个 IPNS 目录均可访问
12
+ * - `grantee` 被授权方 DID(通常与 id 相同)
13
+ * - `accessRights` 权限数组,如 ["read", "download"]
14
+ * - `accessRestrictions` 访问限制:{ expiresAt, maxDownloads, ipWhitelist }
15
+ * - `owner` 文件所有者 DID
16
+ * - `standard` 协议版本号
17
+ * - `status` 凭证状态("active" | "revoked")
18
+ * @param meta - 签发元数据(id、expirationDate 等)
19
+ * @returns VCIssuanceDescriptor,可直接传入 @jccdex/did 的 issueVC()
20
+ */
21
+ export declare function buildFileAccessAuthorizationDescriptor(brand: BrandId, subject: Record<string, unknown> & {
22
+ id: string;
23
+ }, meta: DescriptorMeta): VCIssuanceDescriptor;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildFileAccessAuthorizationDescriptor = buildFileAccessAuthorizationDescriptor;
4
+ const inline_contexts_js_1 = require("../inline-contexts.js");
5
+ const vc_types_js_1 = require("../vc-types.js");
6
+ /**
7
+ * 构建文件访问授权 VC 签发描述符(基于 IPFS/IPNS 存储模型)。
8
+ *
9
+ * 两品牌词汇结构相同,仅 URL 命名空间不同。
10
+ *
11
+ * @param brand - 品牌 ID:"ccdao" | "jdid"
12
+ * @param subject - credentialSubject,必须包含 `id`(被授权方 DID)及以下业务字段:
13
+ * - `ipnsName` IPNS 固定入口(被授权方用来访问文件/目录的稳定地址)
14
+ * - `resourceType` 授权粒度:"file" | "directory"
15
+ * - `resourcePath` (可选)目录内子路径,为空则整个 IPNS 目录均可访问
16
+ * - `grantee` 被授权方 DID(通常与 id 相同)
17
+ * - `accessRights` 权限数组,如 ["read", "download"]
18
+ * - `accessRestrictions` 访问限制:{ expiresAt, maxDownloads, ipWhitelist }
19
+ * - `owner` 文件所有者 DID
20
+ * - `standard` 协议版本号
21
+ * - `status` 凭证状态("active" | "revoked")
22
+ * @param meta - 签发元数据(id、expirationDate 等)
23
+ * @returns VCIssuanceDescriptor,可直接传入 @jccdex/did 的 issueVC()
24
+ */
25
+ function buildFileAccessAuthorizationDescriptor(brand, subject, meta) {
26
+ return {
27
+ types: [vc_types_js_1.VC_TYPES.FILE_ACCESS_AUTHORIZATION],
28
+ contexts: [inline_contexts_js_1.W3C_VC_CONTEXT_URL, (0, inline_contexts_js_1.getFileAccessAuthorizationContext)(brand)],
29
+ subject,
30
+ id: meta.id,
31
+ expirationDate: meta.expirationDate,
32
+ issuanceDate: meta.issuanceDate,
33
+ issuer: meta.issuer
34
+ };
35
+ }
package/lib/vc-types.d.ts CHANGED
@@ -3,5 +3,6 @@ export declare const VC_TYPES: {
3
3
  readonly NFT_OWNERSHIP: "NFTOwnership";
4
4
  readonly NFT_USAGE_AUTHORIZATION: "NFTUsageAuthorization";
5
5
  readonly PHONE_VERIFICATION: "PhoneVerificationCredential";
6
+ readonly FILE_ACCESS_AUTHORIZATION: "FileAccessAuthorization";
6
7
  };
7
8
  export type VCType = (typeof VC_TYPES)[keyof typeof VC_TYPES];
package/lib/vc-types.js CHANGED
@@ -5,5 +5,6 @@ exports.VC_TYPES = void 0;
5
5
  exports.VC_TYPES = {
6
6
  NFT_OWNERSHIP: "NFTOwnership",
7
7
  NFT_USAGE_AUTHORIZATION: "NFTUsageAuthorization",
8
- PHONE_VERIFICATION: "PhoneVerificationCredential"
8
+ PHONE_VERIFICATION: "PhoneVerificationCredential",
9
+ FILE_ACCESS_AUTHORIZATION: "FileAccessAuthorization"
9
10
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jccdex/vc-vocabularies",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "VC vocabulary and issuance profiles for JCCDEx DID ecosystem",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./lib/index.d.ts",
@@ -7,6 +7,7 @@
7
7
  "NFTOwnership": "https://ccda.ooo/vc/v1#NFTOwnership",
8
8
  "NFTUsageAuthorization": "https://ccda.ooo/vc/v1#NFTUsageAuthorization",
9
9
  "PhoneVerificationCredential": "https://ccda.ooo/vc/v1#PhoneVerificationCredential",
10
+ "FileAccessAuthorization": "https://ccda.ooo/vc/v1#FileAccessAuthorization",
10
11
  "version": "https://ccda.ooo/did/v1#version",
11
12
  "chainId": "https://ccda.ooo/did/v1#chainId",
12
13
  "contractAddress": "https://ccda.ooo/did/v1#contractAddress",
@@ -25,6 +26,9 @@
25
26
  "updateAt": "https://ccda.ooo/did/v1#updateAt",
26
27
  "verifierId": "https://ccda.ooo/did/v1#verifierId"
27
28
  }
28
- }
29
+ },
30
+ "ipnsName": "https://ccda.ooo/did/v1#ipnsName",
31
+ "resourceType": "https://ccda.ooo/did/v1#resourceType",
32
+ "resourcePath": "https://ccda.ooo/did/v1#resourcePath"
29
33
  }
30
34
  }
@@ -15,6 +15,15 @@
15
15
  "territories": "https://ccda.ooo/vc/v1#territories",
16
16
  "platforms": "https://ccda.ooo/vc/v1#platforms"
17
17
  }
18
+ },
19
+ "accessRights": "https://ccda.ooo/vc/v1#accessRights",
20
+ "accessRestrictions": {
21
+ "@id": "https://ccda.ooo/vc/v1#accessRestrictions",
22
+ "@context": {
23
+ "expiresAt": "https://ccda.ooo/vc/v1#expiresAt",
24
+ "maxDownloads": "https://ccda.ooo/vc/v1#maxDownloads",
25
+ "ipWhitelist": "https://ccda.ooo/vc/v1#ipWhitelist"
26
+ }
18
27
  }
19
28
  }
20
29
  }
@@ -7,6 +7,7 @@
7
7
  "NFTOwnership": "https://jdid.cn/vc/v1#NFTOwnership",
8
8
  "NFTUsageAuthorization": "https://jdid.cn/vc/v1#NFTUsageAuthorization",
9
9
  "PhoneVerificationCredential": "https://jdid.cn/vc/v1#PhoneVerificationCredential",
10
+ "FileAccessAuthorization": "https://jdid.cn/vc/v1#FileAccessAuthorization",
10
11
  "version": "https://jdid.cn/did/v1#version",
11
12
  "chainId": "https://jdid.cn/did/v1#chainId",
12
13
  "contractAddress": "https://jdid.cn/did/v1#contractAddress",
@@ -25,6 +26,9 @@
25
26
  "updateAt": "https://jdid.cn/did/v1#updateAt",
26
27
  "verifierId": "https://jdid.cn/did/v1#verifierId"
27
28
  }
28
- }
29
+ },
30
+ "ipnsName": "https://jdid.cn/did/v1#ipnsName",
31
+ "resourceType": "https://jdid.cn/did/v1#resourceType",
32
+ "resourcePath": "https://jdid.cn/did/v1#resourcePath"
29
33
  }
30
34
  }
@@ -15,6 +15,15 @@
15
15
  "territories": "https://jdid.cn/vc/v1#territories",
16
16
  "platforms": "https://jdid.cn/vc/v1#platforms"
17
17
  }
18
+ },
19
+ "accessRights": "https://jdid.cn/vc/v1#accessRights",
20
+ "accessRestrictions": {
21
+ "@id": "https://jdid.cn/vc/v1#accessRestrictions",
22
+ "@context": {
23
+ "expiresAt": "https://jdid.cn/vc/v1#expiresAt",
24
+ "maxDownloads": "https://jdid.cn/vc/v1#maxDownloads",
25
+ "ipWhitelist": "https://jdid.cn/vc/v1#ipWhitelist"
26
+ }
18
27
  }
19
28
  }
20
29
  }