@powerhousedao/renown-package 0.0.6 → 0.0.30
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/dist/document-models/renown-credential/gen/document-model.js +22 -8
- package/dist/document-models/renown-credential/gen/manager/error.d.ts +13 -3
- package/dist/document-models/renown-credential/gen/manager/error.js +18 -4
- package/dist/document-models/renown-credential/gen/manager/object.d.ts +1 -1
- package/dist/document-models/renown-credential/gen/object.d.ts +1 -1
- package/dist/document-models/renown-credential/gen/ph-factories.js +7 -5
- package/dist/document-models/renown-credential/gen/reducer.d.ts +1 -1
- package/dist/document-models/renown-credential/gen/schema/types.d.ts +11 -14
- package/dist/document-models/renown-credential/gen/schema/zod.js +8 -12
- package/dist/document-models/renown-credential/gen/utils.d.ts +1 -1
- package/dist/document-models/renown-credential/gen/utils.js +7 -5
- package/dist/document-models/renown-credential/src/reducers/manager.js +77 -27
- package/dist/editors/renown-credential-editor/editor.js +7 -24
- package/dist/processors/renown-credential/index.js +33 -22
- package/dist/processors/renown-credential/migrations.js +9 -7
- package/dist/processors/renown-credential/schema.d.ts +8 -6
- package/dist/style.css +7 -0
- package/dist/subgraphs/renown-credential/schema.js +14 -16
- package/dist/subgraphs/renown-read-model/resolvers.js +5 -3
- package/dist/subgraphs/renown-read-model/schema.js +8 -6
- package/package.json +16 -14
|
@@ -27,10 +27,17 @@ export const documentModel = {
|
|
|
27
27
|
template: "",
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
|
-
code: "
|
|
31
|
-
description: "
|
|
32
|
-
id: "
|
|
33
|
-
name: "
|
|
30
|
+
code: "INVALID_JWT_PAYLOAD",
|
|
31
|
+
description: "JWT payload does not contain valid W3C Verifiable Credential fields",
|
|
32
|
+
id: "invalid-jwt-payload-error",
|
|
33
|
+
name: "InvalidJwtPayloadError",
|
|
34
|
+
template: "",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
code: "JWT_VERIFICATION_FAILED",
|
|
38
|
+
description: "Failed to verify the JWT signature or the JWT is malformed",
|
|
39
|
+
id: "jwt-verification-error",
|
|
40
|
+
name: "JwtVerificationError",
|
|
34
41
|
template: "",
|
|
35
42
|
},
|
|
36
43
|
{
|
|
@@ -40,12 +47,19 @@ export const documentModel = {
|
|
|
40
47
|
name: "InvalidClaimsError",
|
|
41
48
|
template: "",
|
|
42
49
|
},
|
|
50
|
+
{
|
|
51
|
+
code: "MISSING_TYPE",
|
|
52
|
+
description: "The type field is required and must include VerifiableCredential",
|
|
53
|
+
id: "missing-type-error",
|
|
54
|
+
name: "MissingTypeError",
|
|
55
|
+
template: "",
|
|
56
|
+
},
|
|
43
57
|
],
|
|
44
58
|
examples: [],
|
|
45
59
|
id: "366dfd44-377f-42d7-949d-a8d82b6a909d",
|
|
46
60
|
name: "INIT",
|
|
47
|
-
reducer:
|
|
48
|
-
schema: "input InitInput {\n
|
|
61
|
+
reducer: "// NOTE: JWT should be cryptographically verified using verifyCredential()\n// from did-jwt-vc BEFORE dispatching this action. This reducer only decodes\n// and extracts the credential fields from the JWT payload.\n\n// Decode the JWT to extract payload\nlet decoded;\ntry {\n decoded = decodeJWT(action.input.jwt);\n} catch (e) {\n const error = e as Error;\n throw new JwtVerificationError(`Failed to decode JWT: ${error.message}`);\n}\n\nconst payload = decoded.payload as JwtPayload;\n\n// Validate minimum required JWT fields\nif (!payload.iss) {\n throw new InvalidJwtPayloadError('JWT payload missing issuer (iss field)');\n}\n\n// Extract the verifiable credential from the payload (if present)\nconst vc = payload.vc as VerifiableCredentialPayload | undefined;\n\nif (!vc) {\n throw new InvalidJwtPayloadError('JWT payload does not contain a verifiable credential (vc field)');\n}\n\n// Store the complete VC payload for maximum flexibility\nstate.vcPayload = JSON.stringify(vc);\n\n// Extract common W3C VC fields if present (but don't fail if missing)\n// Context\nif (vc['@context']) {\n const context = Array.isArray(vc['@context']) ? vc['@context'] : [vc['@context']];\n state.context = context;\n} else {\n state.context = null;\n}\n\n// Type\nif (vc.type) {\n const type = Array.isArray(vc.type) ? vc.type : [vc.type];\n state.type = type;\n} else {\n state.type = null;\n}\n\n// Credential Subject - store as JSON string for flexibility\nif (vc.credentialSubject !== undefined) {\n const credentialSubjectStr = typeof vc.credentialSubject === 'string'\n ? vc.credentialSubject\n : JSON.stringify(vc.credentialSubject);\n state.credentialSubject = credentialSubjectStr;\n} else {\n state.credentialSubject = null;\n}\n\n// Issuer (from JWT payload)\nstate.issuer = payload.iss;\n\n// Issuance date (JWT uses 'iat' or 'nbf')\nif (payload.nbf || payload.iat) {\n const issuanceTimestamp = (payload.nbf || payload.iat)!;\n state.issuanceDate = new Date(issuanceTimestamp * 1000).toISOString();\n} else {\n state.issuanceDate = null;\n}\n\n// Expiration date (from JWT exp or VC expirationDate)\nif (payload.exp) {\n state.expirationDate = new Date(payload.exp * 1000).toISOString();\n} else if (vc.expirationDate) {\n state.expirationDate = vc.expirationDate;\n} else {\n state.expirationDate = null;\n}\n\n// Credential ID (JWT uses 'jti', VC uses 'id')\nstate.id = payload.jti || vc.id || null;\n\n// Credential Status (optional W3C VC field)\nstate.credentialStatus = vc.credentialStatus || null;\n\n// Store JWT token\nstate.jwt = action.input.jwt;\nstate.jwtVerified = true;\n\n// Initialize revocation tracking\nstate.revoked = false;\nstate.revokedAt = null;\nstate.revocationReason = null;",
|
|
62
|
+
schema: "input InitInput {\n jwt: String!\n}",
|
|
49
63
|
scope: "global",
|
|
50
64
|
template: "",
|
|
51
65
|
},
|
|
@@ -130,8 +144,8 @@ export const documentModel = {
|
|
|
130
144
|
state: {
|
|
131
145
|
global: {
|
|
132
146
|
examples: [],
|
|
133
|
-
initialValue: '"{\\n \\"
|
|
134
|
-
schema: 'type CredentialStatus {\n id: String!\n type: String!\n statusPurpose: String!\n statusListIndex: String!\n statusListCredential: String!\n}\n\ntype RenownCredentialState {\n "W3C VC
|
|
147
|
+
initialValue: '"{\\n \\"vcPayload\\": null,\\n \\"context\\": null,\\n \\"id\\": null,\\n \\"type\\": null,\\n \\"issuer\\": null,\\n \\"issuanceDate\\": null,\\n \\"credentialSubject\\": null,\\n \\"expirationDate\\": null,\\n \\"credentialStatus\\": null,\\n \\"jwt\\": null,\\n \\"jwtVerified\\": false,\\n \\"revoked\\": false,\\n \\"revokedAt\\": null,\\n \\"revocationReason\\": null\\n}"',
|
|
148
|
+
schema: 'type CredentialStatus {\n id: String!\n type: String!\n statusPurpose: String!\n statusListIndex: String!\n statusListCredential: String!\n}\n\ntype RenownCredentialState {\n "JWT token containing the Verifiable Credential"\n jwt: String\n jwtVerified: Boolean\n\n "Complete VC Payload - extracted from JWT for convenience and flexibility"\n vcPayload: String\n\n "W3C VC Common Fields - extracted for querying convenience, may be null for non-standard VCs"\n context: [String!]\n id: String\n type: [String!]\n issuer: String\n issuanceDate: DateTime\n credentialSubject: String\n\n "W3C VC Optional Fields"\n expirationDate: DateTime\n credentialStatus: CredentialStatus\n\n "Revocation tracking"\n revoked: Boolean\n revokedAt: DateTime\n revocationReason: String\n}',
|
|
135
149
|
},
|
|
136
150
|
local: {
|
|
137
151
|
examples: [],
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type ErrorCode = "MissingContextError" | "
|
|
1
|
+
export type ErrorCode = "MissingContextError" | "InvalidJwtPayloadError" | "JwtVerificationError" | "InvalidClaimsError" | "MissingTypeError" | "AlreadyRevokedError" | "CredentialRevokedError" | "InvalidStatusPurposeError";
|
|
2
2
|
export interface ReducerError {
|
|
3
3
|
errorCode: ErrorCode;
|
|
4
4
|
}
|
|
@@ -6,7 +6,11 @@ export declare class MissingContextError extends Error implements ReducerError {
|
|
|
6
6
|
errorCode: ErrorCode;
|
|
7
7
|
constructor(message?: string);
|
|
8
8
|
}
|
|
9
|
-
export declare class
|
|
9
|
+
export declare class InvalidJwtPayloadError extends Error implements ReducerError {
|
|
10
|
+
errorCode: ErrorCode;
|
|
11
|
+
constructor(message?: string);
|
|
12
|
+
}
|
|
13
|
+
export declare class JwtVerificationError extends Error implements ReducerError {
|
|
10
14
|
errorCode: ErrorCode;
|
|
11
15
|
constructor(message?: string);
|
|
12
16
|
}
|
|
@@ -14,6 +18,10 @@ export declare class InvalidClaimsError extends Error implements ReducerError {
|
|
|
14
18
|
errorCode: ErrorCode;
|
|
15
19
|
constructor(message?: string);
|
|
16
20
|
}
|
|
21
|
+
export declare class MissingTypeError extends Error implements ReducerError {
|
|
22
|
+
errorCode: ErrorCode;
|
|
23
|
+
constructor(message?: string);
|
|
24
|
+
}
|
|
17
25
|
export declare class AlreadyRevokedError extends Error implements ReducerError {
|
|
18
26
|
errorCode: ErrorCode;
|
|
19
27
|
constructor(message?: string);
|
|
@@ -29,8 +37,10 @@ export declare class InvalidStatusPurposeError extends Error implements ReducerE
|
|
|
29
37
|
export declare const errors: {
|
|
30
38
|
Init: {
|
|
31
39
|
MissingContextError: typeof MissingContextError;
|
|
32
|
-
|
|
40
|
+
InvalidJwtPayloadError: typeof InvalidJwtPayloadError;
|
|
41
|
+
JwtVerificationError: typeof JwtVerificationError;
|
|
33
42
|
InvalidClaimsError: typeof InvalidClaimsError;
|
|
43
|
+
MissingTypeError: typeof MissingTypeError;
|
|
34
44
|
};
|
|
35
45
|
Revoke: {
|
|
36
46
|
AlreadyRevokedError: typeof AlreadyRevokedError;
|
|
@@ -4,9 +4,15 @@ export class MissingContextError extends Error {
|
|
|
4
4
|
super(message);
|
|
5
5
|
}
|
|
6
6
|
}
|
|
7
|
-
export class
|
|
8
|
-
errorCode = "
|
|
9
|
-
constructor(message = "
|
|
7
|
+
export class InvalidJwtPayloadError extends Error {
|
|
8
|
+
errorCode = "InvalidJwtPayloadError";
|
|
9
|
+
constructor(message = "InvalidJwtPayloadError") {
|
|
10
|
+
super(message);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export class JwtVerificationError extends Error {
|
|
14
|
+
errorCode = "JwtVerificationError";
|
|
15
|
+
constructor(message = "JwtVerificationError") {
|
|
10
16
|
super(message);
|
|
11
17
|
}
|
|
12
18
|
}
|
|
@@ -16,6 +22,12 @@ export class InvalidClaimsError extends Error {
|
|
|
16
22
|
super(message);
|
|
17
23
|
}
|
|
18
24
|
}
|
|
25
|
+
export class MissingTypeError extends Error {
|
|
26
|
+
errorCode = "MissingTypeError";
|
|
27
|
+
constructor(message = "MissingTypeError") {
|
|
28
|
+
super(message);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
19
31
|
export class AlreadyRevokedError extends Error {
|
|
20
32
|
errorCode = "AlreadyRevokedError";
|
|
21
33
|
constructor(message = "AlreadyRevokedError") {
|
|
@@ -37,8 +49,10 @@ export class InvalidStatusPurposeError extends Error {
|
|
|
37
49
|
export const errors = {
|
|
38
50
|
Init: {
|
|
39
51
|
MissingContextError,
|
|
40
|
-
|
|
52
|
+
InvalidJwtPayloadError,
|
|
53
|
+
JwtVerificationError,
|
|
41
54
|
InvalidClaimsError,
|
|
55
|
+
MissingTypeError,
|
|
42
56
|
},
|
|
43
57
|
Revoke: {
|
|
44
58
|
AlreadyRevokedError,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseDocumentClass } from "document-model";
|
|
2
|
-
import { RenownCredentialPHState } from "../ph-factories.js";
|
|
2
|
+
import { type RenownCredentialPHState } from "../ph-factories.js";
|
|
3
3
|
import { type InitInput, type RevokeInput, type UpdateCredentialSubjectInput, type SetJwtInput, type SetCredentialStatusInput } from "../types.js";
|
|
4
4
|
export default class RenownCredential_Manager extends BaseDocumentClass<RenownCredentialPHState> {
|
|
5
5
|
init(input: InitInput): this;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseDocumentClass, type SignalDispatch } from "document-model";
|
|
2
|
-
import { RenownCredentialPHState } from "./ph-factories.js";
|
|
2
|
+
import { type RenownCredentialPHState } from "./ph-factories.js";
|
|
3
3
|
import RenownCredential_Manager from "./manager/object.js";
|
|
4
4
|
export * from "./manager/object.js";
|
|
5
5
|
interface RenownCredential extends RenownCredential_Manager {
|
|
@@ -5,15 +5,17 @@ import { createBaseState, defaultBaseState, } from "document-model";
|
|
|
5
5
|
import { createDocument } from "./utils.js";
|
|
6
6
|
export function defaultGlobalState() {
|
|
7
7
|
return {
|
|
8
|
-
|
|
8
|
+
vcPayload: null,
|
|
9
|
+
context: null,
|
|
9
10
|
id: null,
|
|
10
|
-
type:
|
|
11
|
-
issuer:
|
|
12
|
-
issuanceDate:
|
|
13
|
-
credentialSubject:
|
|
11
|
+
type: null,
|
|
12
|
+
issuer: null,
|
|
13
|
+
issuanceDate: null,
|
|
14
|
+
credentialSubject: null,
|
|
14
15
|
expirationDate: null,
|
|
15
16
|
credentialStatus: null,
|
|
16
17
|
jwt: null,
|
|
18
|
+
jwtVerified: false,
|
|
17
19
|
revoked: false,
|
|
18
20
|
revokedAt: null,
|
|
19
21
|
revocationReason: null,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { type StateReducer } from "document-model";
|
|
2
|
-
import { RenownCredentialPHState } from "./ph-factories.js";
|
|
2
|
+
import { type RenownCredentialPHState } from "./ph-factories.js";
|
|
3
3
|
export declare const stateReducer: StateReducer<RenownCredentialPHState>;
|
|
4
4
|
export declare const reducer: import("document-model").Reducer<RenownCredentialPHState>;
|
|
@@ -142,31 +142,28 @@ export type CredentialStatus = {
|
|
|
142
142
|
type: Scalars["String"]["output"];
|
|
143
143
|
};
|
|
144
144
|
export type InitInput = {
|
|
145
|
-
|
|
146
|
-
credentialSubject: Scalars["String"]["input"];
|
|
147
|
-
expirationDate?: InputMaybe<Scalars["DateTime"]["input"]>;
|
|
148
|
-
id?: InputMaybe<Scalars["String"]["input"]>;
|
|
149
|
-
issuanceDate: Scalars["DateTime"]["input"];
|
|
150
|
-
issuer: Scalars["String"]["input"];
|
|
151
|
-
type?: InputMaybe<Array<Scalars["String"]["input"]>>;
|
|
145
|
+
jwt: Scalars["String"]["input"];
|
|
152
146
|
};
|
|
153
147
|
export type RenownCredentialState = {
|
|
154
|
-
/** W3C VC
|
|
155
|
-
context: Array<Scalars["String"]["output"]
|
|
148
|
+
/** W3C VC Common Fields - extracted for querying convenience, may be null for non-standard VCs */
|
|
149
|
+
context: Maybe<Array<Scalars["String"]["output"]>>;
|
|
156
150
|
credentialStatus: Maybe<CredentialStatus>;
|
|
157
|
-
credentialSubject: Scalars["String"]["output"]
|
|
151
|
+
credentialSubject: Maybe<Scalars["String"]["output"]>;
|
|
158
152
|
/** W3C VC Optional Fields */
|
|
159
153
|
expirationDate: Maybe<Scalars["DateTime"]["output"]>;
|
|
160
154
|
id: Maybe<Scalars["String"]["output"]>;
|
|
161
|
-
issuanceDate: Scalars["DateTime"]["output"]
|
|
162
|
-
issuer: Scalars["String"]["output"]
|
|
163
|
-
/** JWT
|
|
155
|
+
issuanceDate: Maybe<Scalars["DateTime"]["output"]>;
|
|
156
|
+
issuer: Maybe<Scalars["String"]["output"]>;
|
|
157
|
+
/** JWT token containing the Verifiable Credential */
|
|
164
158
|
jwt: Maybe<Scalars["String"]["output"]>;
|
|
159
|
+
jwtVerified: Maybe<Scalars["Boolean"]["output"]>;
|
|
165
160
|
revocationReason: Maybe<Scalars["String"]["output"]>;
|
|
166
161
|
/** Revocation tracking */
|
|
167
162
|
revoked: Maybe<Scalars["Boolean"]["output"]>;
|
|
168
163
|
revokedAt: Maybe<Scalars["DateTime"]["output"]>;
|
|
169
|
-
type: Array<Scalars["String"]["output"]
|
|
164
|
+
type: Maybe<Array<Scalars["String"]["output"]>>;
|
|
165
|
+
/** Complete VC Payload - extracted from JWT for convenience and flexibility */
|
|
166
|
+
vcPayload: Maybe<Scalars["String"]["output"]>;
|
|
170
167
|
};
|
|
171
168
|
export type RevokeInput = {
|
|
172
169
|
reason?: InputMaybe<Scalars["String"]["input"]>;
|
|
@@ -15,30 +15,26 @@ export function CredentialStatusSchema() {
|
|
|
15
15
|
}
|
|
16
16
|
export function InitInputSchema() {
|
|
17
17
|
return z.object({
|
|
18
|
-
|
|
19
|
-
credentialSubject: z.string(),
|
|
20
|
-
expirationDate: z.string().datetime().nullish(),
|
|
21
|
-
id: z.string().nullish(),
|
|
22
|
-
issuanceDate: z.string().datetime(),
|
|
23
|
-
issuer: z.string(),
|
|
24
|
-
type: z.array(z.string()).nullish(),
|
|
18
|
+
jwt: z.string(),
|
|
25
19
|
});
|
|
26
20
|
}
|
|
27
21
|
export function RenownCredentialStateSchema() {
|
|
28
22
|
return z.object({
|
|
29
23
|
__typename: z.literal("RenownCredentialState").optional(),
|
|
30
|
-
context: z.array(z.string()),
|
|
24
|
+
context: z.array(z.string()).nullable(),
|
|
31
25
|
credentialStatus: CredentialStatusSchema().nullable(),
|
|
32
|
-
credentialSubject: z.string(),
|
|
26
|
+
credentialSubject: z.string().nullable(),
|
|
33
27
|
expirationDate: z.string().datetime().nullable(),
|
|
34
28
|
id: z.string().nullable(),
|
|
35
|
-
issuanceDate: z.string().datetime(),
|
|
36
|
-
issuer: z.string(),
|
|
29
|
+
issuanceDate: z.string().datetime().nullable(),
|
|
30
|
+
issuer: z.string().nullable(),
|
|
37
31
|
jwt: z.string().nullable(),
|
|
32
|
+
jwtVerified: z.boolean().nullable(),
|
|
38
33
|
revocationReason: z.string().nullable(),
|
|
39
34
|
revoked: z.boolean().nullable(),
|
|
40
35
|
revokedAt: z.string().datetime().nullable(),
|
|
41
|
-
type: z.array(z.string()),
|
|
36
|
+
type: z.array(z.string()).nullable(),
|
|
37
|
+
vcPayload: z.string().nullable(),
|
|
42
38
|
});
|
|
43
39
|
}
|
|
44
40
|
export function RevokeInputSchema() {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type CreateDocument, type CreateState, type LoadFromFile, type LoadFromInput } from "document-model";
|
|
2
2
|
import { type RenownCredentialState, type RenownCredentialLocalState } from "./types.js";
|
|
3
|
-
import { RenownCredentialPHState } from "./ph-factories.js";
|
|
3
|
+
import { type RenownCredentialPHState } from "./ph-factories.js";
|
|
4
4
|
export declare const initialGlobalState: RenownCredentialState;
|
|
5
5
|
export declare const initialLocalState: RenownCredentialLocalState;
|
|
6
6
|
export declare const createState: CreateState<RenownCredentialPHState>;
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { baseCreateDocument, baseSaveToFile, baseSaveToFileHandle, baseLoadFromFile, baseLoadFromInput, defaultBaseState, generateId, } from "document-model";
|
|
2
2
|
import { reducer } from "./reducer.js";
|
|
3
3
|
export const initialGlobalState = {
|
|
4
|
-
|
|
4
|
+
vcPayload: null,
|
|
5
|
+
context: null,
|
|
5
6
|
id: null,
|
|
6
|
-
type:
|
|
7
|
-
issuer:
|
|
8
|
-
issuanceDate:
|
|
9
|
-
credentialSubject:
|
|
7
|
+
type: null,
|
|
8
|
+
issuer: null,
|
|
9
|
+
issuanceDate: null,
|
|
10
|
+
credentialSubject: null,
|
|
10
11
|
expirationDate: null,
|
|
11
12
|
credentialStatus: null,
|
|
12
13
|
jwt: null,
|
|
14
|
+
jwtVerified: false,
|
|
13
15
|
revoked: false,
|
|
14
16
|
revokedAt: null,
|
|
15
17
|
revocationReason: null,
|
|
@@ -1,36 +1,86 @@
|
|
|
1
|
-
import { InvalidStatusPurposeError,
|
|
1
|
+
import { InvalidStatusPurposeError, InvalidClaimsError, CredentialRevokedError, AlreadyRevokedError, JwtVerificationError, InvalidJwtPayloadError, } from "../../gen/manager/error.js";
|
|
2
|
+
import { decodeJWT } from 'did-jwt';
|
|
2
3
|
export const reducer = {
|
|
3
4
|
initOperation(state, action, dispatch) {
|
|
4
|
-
//
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
throw new MissingContextError("Context must include https://www.w3.org/2018/credentials/v1");
|
|
10
|
-
}
|
|
11
|
-
// Validate type
|
|
12
|
-
const type = action.input.type && action.input.type.length > 0
|
|
13
|
-
? action.input.type
|
|
14
|
-
: ["VerifiableCredential"];
|
|
15
|
-
if (!type.includes("VerifiableCredential")) {
|
|
16
|
-
throw new MissingTypeError("Type must include VerifiableCredential");
|
|
17
|
-
}
|
|
18
|
-
// Validate credentialSubject is valid JSON
|
|
5
|
+
// NOTE: JWT should be cryptographically verified using verifyCredential()
|
|
6
|
+
// from did-jwt-vc BEFORE dispatching this action. This reducer only decodes
|
|
7
|
+
// and extracts the credential fields from the JWT payload.
|
|
8
|
+
// Decode the JWT to extract payload
|
|
9
|
+
let decoded;
|
|
19
10
|
try {
|
|
20
|
-
|
|
11
|
+
decoded = decodeJWT(action.input.jwt);
|
|
21
12
|
}
|
|
22
13
|
catch (e) {
|
|
23
|
-
|
|
14
|
+
const error = e;
|
|
15
|
+
throw new JwtVerificationError(`Failed to decode JWT: ${error.message}`);
|
|
24
16
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
17
|
+
const payload = decoded.payload;
|
|
18
|
+
// Validate minimum required JWT fields
|
|
19
|
+
if (!payload.iss) {
|
|
20
|
+
throw new InvalidJwtPayloadError('JWT payload missing issuer (iss field)');
|
|
21
|
+
}
|
|
22
|
+
// Extract the verifiable credential from the payload (if present)
|
|
23
|
+
const vc = payload.vc;
|
|
24
|
+
if (!vc) {
|
|
25
|
+
throw new InvalidJwtPayloadError('JWT payload does not contain a verifiable credential (vc field)');
|
|
26
|
+
}
|
|
27
|
+
// Store the complete VC payload for maximum flexibility
|
|
28
|
+
state.vcPayload = JSON.stringify(vc);
|
|
29
|
+
// Extract common W3C VC fields if present (but don't fail if missing)
|
|
30
|
+
// Context
|
|
31
|
+
if (vc['@context']) {
|
|
32
|
+
const context = Array.isArray(vc['@context']) ? vc['@context'] : [vc['@context']];
|
|
33
|
+
state.context = context;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
state.context = null;
|
|
37
|
+
}
|
|
38
|
+
// Type
|
|
39
|
+
if (vc.type) {
|
|
40
|
+
const type = Array.isArray(vc.type) ? vc.type : [vc.type];
|
|
41
|
+
state.type = type;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
state.type = null;
|
|
45
|
+
}
|
|
46
|
+
// Credential Subject - store as JSON string for flexibility
|
|
47
|
+
if (vc.credentialSubject !== undefined) {
|
|
48
|
+
const credentialSubjectStr = typeof vc.credentialSubject === 'string'
|
|
49
|
+
? vc.credentialSubject
|
|
50
|
+
: JSON.stringify(vc.credentialSubject);
|
|
51
|
+
state.credentialSubject = credentialSubjectStr;
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
state.credentialSubject = null;
|
|
55
|
+
}
|
|
56
|
+
// Issuer (from JWT payload)
|
|
57
|
+
state.issuer = payload.iss;
|
|
58
|
+
// Issuance date (JWT uses 'iat' or 'nbf')
|
|
59
|
+
if (payload.nbf || payload.iat) {
|
|
60
|
+
const issuanceTimestamp = (payload.nbf || payload.iat);
|
|
61
|
+
state.issuanceDate = new Date(issuanceTimestamp * 1000).toISOString();
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
state.issuanceDate = null;
|
|
65
|
+
}
|
|
66
|
+
// Expiration date (from JWT exp or VC expirationDate)
|
|
67
|
+
if (payload.exp) {
|
|
68
|
+
state.expirationDate = new Date(payload.exp * 1000).toISOString();
|
|
69
|
+
}
|
|
70
|
+
else if (vc.expirationDate) {
|
|
71
|
+
state.expirationDate = vc.expirationDate;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
state.expirationDate = null;
|
|
75
|
+
}
|
|
76
|
+
// Credential ID (JWT uses 'jti', VC uses 'id')
|
|
77
|
+
state.id = payload.jti || vc.id || null;
|
|
78
|
+
// Credential Status (optional W3C VC field)
|
|
79
|
+
state.credentialStatus = vc.credentialStatus || null;
|
|
80
|
+
// Store JWT token
|
|
81
|
+
state.jwt = action.input.jwt;
|
|
82
|
+
state.jwtVerified = true;
|
|
83
|
+
// Initialize revocation tracking
|
|
34
84
|
state.revoked = false;
|
|
35
85
|
state.revokedAt = null;
|
|
36
86
|
state.revocationReason = null;
|
|
@@ -15,25 +15,13 @@ export function Editor(props) {
|
|
|
15
15
|
const [isSettingJwt, setIsSettingJwt] = useState(false);
|
|
16
16
|
const [isSettingStatus, setIsSettingStatus] = useState(false);
|
|
17
17
|
const { state: { global }, } = typedDocument;
|
|
18
|
-
const { context, id: credentialId, type, issuer, issuanceDate, credentialSubject, expirationDate, credentialStatus, jwt, revoked, revokedAt, revocationReason, } = global;
|
|
18
|
+
const { vcPayload, context, id: credentialId, type, issuer, issuanceDate, credentialSubject, expirationDate, credentialStatus, jwt, revoked, revokedAt, revocationReason, } = global;
|
|
19
19
|
const isInitialized = issuer && issuanceDate;
|
|
20
|
-
// Initialize credential
|
|
20
|
+
// Initialize credential from JWT
|
|
21
21
|
const handleInit = useCallback((values) => {
|
|
22
22
|
try {
|
|
23
|
-
const contextArray = values.context
|
|
24
|
-
? values.context.split(",").map((s) => s.trim())
|
|
25
|
-
: undefined;
|
|
26
|
-
const typeArray = values.type
|
|
27
|
-
? values.type.split(",").map((s) => s.trim())
|
|
28
|
-
: undefined;
|
|
29
23
|
dispatch(actions.init({
|
|
30
|
-
|
|
31
|
-
issuanceDate: new Date().toISOString(),
|
|
32
|
-
credentialSubject: values.credentialSubject,
|
|
33
|
-
expirationDate: values.expirationDate || undefined,
|
|
34
|
-
context: contextArray,
|
|
35
|
-
type: typeArray,
|
|
36
|
-
id: values.id,
|
|
24
|
+
jwt: values.jwt,
|
|
37
25
|
}));
|
|
38
26
|
setIsInitializing(false);
|
|
39
27
|
}
|
|
@@ -82,16 +70,11 @@ export function Editor(props) {
|
|
|
82
70
|
e.preventDefault();
|
|
83
71
|
const formData = new FormData(e.target);
|
|
84
72
|
handleInit({
|
|
85
|
-
|
|
86
|
-
credentialSubject: formData.get("credentialSubject"),
|
|
87
|
-
expirationDate: formData.get("expirationDate"),
|
|
88
|
-
context: formData.get("context"),
|
|
89
|
-
type: formData.get("type"),
|
|
90
|
-
id: formData.get("id"),
|
|
73
|
+
jwt: formData.get("jwt"),
|
|
91
74
|
});
|
|
92
|
-
}, children: _jsxs("div", { className: "space-y-6", children: [_jsx(
|
|
75
|
+
}, children: _jsxs("div", { className: "space-y-6", children: [_jsx(TextareaField, { name: "jwt", label: "JWT (JSON Web Token)", required: true, placeholder: "eyJhbGciOiJFUzI1NksifQ.eyJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIl0sImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImlkIjoiZGlkOmV4YW1wbGU6MTIzIn19LCJzdWIiOiJkaWQ6ZXhhbXBsZToxMjMiLCJuYmYiOjE3MDkyMDAwMDAsImlzcyI6ImRpZDpleGFtcGxlOmlzc3VlciJ9.signature", description: "Paste the signed JWT representing a W3C Verifiable Credential. The JWT should be cryptographically verified before submitting.", rows: 6 }), _jsx("div", { className: "flex justify-end pt-4", children: _jsx(Button, { type: "submit", children: "Initialize Credential from JWT" }) })] }) }) })] })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: "bg-white rounded-xl shadow-md border border-gray-200 overflow-hidden", children: [_jsx("div", { className: "px-6 py-5 bg-gray-50", children: _jsx("h2", { className: "text-2xl font-bold text-gray-900", children: "Credential Information" }) }), _jsxs("div", { className: "p-6", children: [_jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-6", children: [_jsxs("div", { className: "bg-gray-50 p-4 rounded-lg border border-gray-200", children: [_jsx("label", { className: "block text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2", children: "Credential ID" }), _jsx("p", { className: "text-sm font-mono text-gray-900 break-all", children: credentialId || (_jsx("span", { className: "text-gray-400 italic", children: "Not set" })) })] }), _jsxs("div", { className: "bg-gray-50 p-4 rounded-lg border border-gray-200", children: [_jsx("label", { className: "block text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2", children: "Issuer" }), _jsx("p", { className: "text-sm font-mono text-gray-900 break-all", children: issuer })] }), _jsxs("div", { className: "bg-gray-50 p-4 rounded-lg border border-gray-200", children: [_jsx("label", { className: "block text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2", children: "Issuance Date" }), _jsx("p", { className: "text-sm text-gray-900", children: issuanceDate
|
|
93
76
|
? new Date(issuanceDate).toLocaleString()
|
|
94
|
-
: "N/A" })] }), _jsxs("div", { className: "bg-gray-50 p-4 rounded-lg border border-gray-200", children: [_jsx("label", { className: "block text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2", children: "Expiration Date" }), _jsx("p", { className: "text-sm text-gray-900", children: expirationDate ? (new Date(expirationDate).toLocaleString()) : (_jsx("span", { className: "text-gray-400 italic", children: "No expiration" })) })] })] }), _jsxs("div", { className: "mt-6 bg-gray-50 p-4 rounded-lg border border-gray-200", children: [_jsx("label", { className: "block text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2", children: "Context" }), _jsx("div", { className: "flex flex-wrap gap-2", children: context && context.map((ctx, i) => (_jsx("span", { className: "inline-block px-2 py-1 text-xs font-mono bg-blue-100 text-blue-800 rounded", children: ctx }, i))) })] }), _jsxs("div", { className: "mt-6 bg-gray-50 p-4 rounded-lg border border-gray-200", children: [_jsx("label", { className: "block text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2", children: "Type" }), _jsx("div", { className: "flex flex-wrap gap-2", children: type && type.map((t, i) => (_jsx("span", { className: "inline-block px-2 py-1 text-xs font-mono bg-green-100 text-green-800 rounded", children: t }, i))) })] })] })] }), _jsxs("div", { className: "bg-white rounded-xl shadow-md border border-gray-200 overflow-hidden", children: [_jsx("div", { className: "px-6 py-5 bg-gray-50", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("h2", { className: "text-2xl font-bold text-gray-900", children: "Credential Subject" }), !revoked && !isEditingSubject && (_jsx(Button, { color: "light", onClick: () => setIsEditingSubject(true), children: "Edit Subject" }))] }) }), _jsx("div", { className: "p-6", children: isEditingSubject ? (_jsx(Form, { onSubmit: (e) => {
|
|
77
|
+
: "N/A" })] }), _jsxs("div", { className: "bg-gray-50 p-4 rounded-lg border border-gray-200", children: [_jsx("label", { className: "block text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2", children: "Expiration Date" }), _jsx("p", { className: "text-sm text-gray-900", children: expirationDate ? (new Date(expirationDate).toLocaleString()) : (_jsx("span", { className: "text-gray-400 italic", children: "No expiration" })) })] })] }), _jsxs("div", { className: "mt-6 bg-gray-50 p-4 rounded-lg border border-gray-200", children: [_jsx("label", { className: "block text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2", children: "Context" }), _jsx("div", { className: "flex flex-wrap gap-2", children: context && context.map((ctx, i) => (_jsx("span", { className: "inline-block px-2 py-1 text-xs font-mono bg-blue-100 text-blue-800 rounded", children: ctx }, i))) })] }), _jsxs("div", { className: "mt-6 bg-gray-50 p-4 rounded-lg border border-gray-200", children: [_jsx("label", { className: "block text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2", children: "Type" }), _jsx("div", { className: "flex flex-wrap gap-2", children: type && type.map((t, i) => (_jsx("span", { className: "inline-block px-2 py-1 text-xs font-mono bg-green-100 text-green-800 rounded", children: t }, i))) })] })] })] }), vcPayload && (_jsxs("div", { className: "bg-white rounded-xl shadow-md border border-gray-200 overflow-hidden", children: [_jsxs("div", { className: "px-6 py-5 bg-purple-50", children: [_jsx("h2", { className: "text-2xl font-bold text-gray-900", children: "Complete Verifiable Credential" }), _jsx("p", { className: "text-sm text-gray-600 mt-1", children: "Full VC payload from JWT - supports any W3C VC structure" })] }), _jsx("div", { className: "p-6", children: _jsx("pre", { className: "bg-gray-50 p-4 rounded-lg border border-gray-200 overflow-auto text-sm max-h-96", children: JSON.stringify(JSON.parse(vcPayload), null, 2) }) })] })), _jsxs("div", { className: "bg-white rounded-xl shadow-md border border-gray-200 overflow-hidden", children: [_jsx("div", { className: "px-6 py-5 bg-gray-50", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("h2", { className: "text-2xl font-bold text-gray-900", children: "Credential Subject" }), !revoked && !isEditingSubject && (_jsx(Button, { color: "light", onClick: () => setIsEditingSubject(true), children: "Edit Subject" }))] }) }), _jsx("div", { className: "p-6", children: isEditingSubject ? (_jsx(Form, { onSubmit: (e) => {
|
|
95
78
|
e.preventDefault();
|
|
96
79
|
const formData = new FormData(e.target);
|
|
97
80
|
handleUpdateSubject(formData.get("credentialSubject"));
|
|
@@ -99,7 +82,7 @@ export function Editor(props) {
|
|
|
99
82
|
e.preventDefault();
|
|
100
83
|
const formData = new FormData(e.target);
|
|
101
84
|
handleSetJwt(formData.get("jwt"));
|
|
102
|
-
}, children: _jsxs("div", { className: "space-y-4", children: [_jsx(TextareaField, { name: "jwt", label: "JWT Token", defaultValue: jwt || "", required: true, rows: 6, description: "Signed JWT representation of the credential" }), _jsxs("div", { className: "flex justify-end space-x-3", children: [_jsx(Button, { color: "light", onClick: () => setIsSettingJwt(false), children: "Cancel" }), _jsx(Button, { type: "submit", children: "Set JWT" })] })] }) })) : jwt ? (_jsx("div", { className: "bg-gray-50 p-4 rounded-lg border border-gray-200", children: _jsx("p", { className: "text-xs font-mono text-gray-900 break-all", children: jwt }) })) : (_jsx("p", { className: "text-gray-500 italic", children: "No JWT set" })) })] }), _jsxs("div", { className: "bg-white rounded-xl shadow-md border border-gray-200 overflow-hidden", children: [_jsx("div", { className: "px-6 py-5 bg-gray-50", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("h2", { className: "text-2xl font-bold text-gray-900", children: "Credential Status (StatusList2021)" }), !credentialStatus && !isSettingStatus && (_jsx(Button, { color: "light", onClick: () => setIsSettingStatus(true), children: "Set Status" }))] }) }), _jsx("div", { className: "p-6", children: isSettingStatus ? (_jsx(Form, { onSubmit: (e) => {
|
|
85
|
+
}, children: _jsxs("div", { className: "space-y-4", children: [_jsx(TextareaField, { name: "jwt", label: "JWT Token", defaultValue: jwt || "", required: true, rows: 6, description: "Signed JWT representation of the credential" }), _jsxs("div", { className: "flex justify-end space-x-3", children: [_jsx(Button, { color: "light", onClick: () => setIsSettingJwt(false), children: "Cancel" }), _jsx(Button, { type: "submit", children: "Set JWT" })] })] }) })) : jwt ? (_jsx(_Fragment, { children: _jsx("div", { className: "bg-gray-50 p-4 rounded-lg border border-gray-200", children: _jsx("p", { className: "text-xs font-mono text-gray-900 break-all", children: jwt }) }) })) : (_jsx("p", { className: "text-gray-500 italic", children: "No JWT set" })) })] }), _jsxs("div", { className: "bg-white rounded-xl shadow-md border border-gray-200 overflow-hidden", children: [_jsx("div", { className: "px-6 py-5 bg-gray-50", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("h2", { className: "text-2xl font-bold text-gray-900", children: "Credential Status (StatusList2021)" }), !credentialStatus && !isSettingStatus && (_jsx(Button, { color: "light", onClick: () => setIsSettingStatus(true), children: "Set Status" }))] }) }), _jsx("div", { className: "p-6", children: isSettingStatus ? (_jsx(Form, { onSubmit: (e) => {
|
|
103
86
|
e.preventDefault();
|
|
104
87
|
const formData = new FormData(e.target);
|
|
105
88
|
handleSetStatus({
|
|
@@ -27,30 +27,37 @@ export class RenownCredentialProcessor extends RelationalDbProcessor {
|
|
|
27
27
|
for (const operation of strand.operations) {
|
|
28
28
|
switch (operation.action.type) {
|
|
29
29
|
case "INIT": {
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
// INIT operation now only receives JWT, all fields are extracted by the reducer
|
|
31
|
+
// Access the document state to get the extracted fields
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
33
|
+
const state = (strand.state)?.global;
|
|
34
|
+
if (state && !existingCredential) {
|
|
32
35
|
await this.relationalDb
|
|
33
36
|
.insertInto("renown_credential")
|
|
34
37
|
.values({
|
|
35
38
|
document_id: documentId,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
jwt: state.jwt || null,
|
|
40
|
+
jwt_verified: state.jwtVerified || false,
|
|
41
|
+
vc_payload: state.vcPayload || null,
|
|
42
|
+
context: state.context ? JSON.stringify(state.context) : null,
|
|
43
|
+
credential_id: state.id || null,
|
|
44
|
+
type: state.type ? JSON.stringify(state.type) : null,
|
|
45
|
+
issuer: state.issuer || null,
|
|
46
|
+
issuance_date: state.issuanceDate
|
|
47
|
+
? new Date(state.issuanceDate)
|
|
48
|
+
: null,
|
|
49
|
+
credential_subject: state.credentialSubject || null,
|
|
50
|
+
expiration_date: state.expirationDate
|
|
51
|
+
? new Date(state.expirationDate)
|
|
44
52
|
: null,
|
|
45
|
-
credential_status_id: null,
|
|
46
|
-
credential_status_type: null,
|
|
47
|
-
credential_status_purpose: null,
|
|
48
|
-
credential_status_list_index: null,
|
|
49
|
-
credential_status_list_credential: null,
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
revocation_reason: null,
|
|
53
|
+
credential_status_id: state.credentialStatus?.id || null,
|
|
54
|
+
credential_status_type: state.credentialStatus?.type || null,
|
|
55
|
+
credential_status_purpose: state.credentialStatus?.statusPurpose || null,
|
|
56
|
+
credential_status_list_index: state.credentialStatus?.statusListIndex || null,
|
|
57
|
+
credential_status_list_credential: state.credentialStatus?.statusListCredential || null,
|
|
58
|
+
revoked: state.revoked || false,
|
|
59
|
+
revoked_at: state.revokedAt ? new Date(state.revokedAt) : null,
|
|
60
|
+
revocation_reason: state.revocationReason || null,
|
|
54
61
|
created_at: new Date(),
|
|
55
62
|
updated_at: new Date(),
|
|
56
63
|
})
|
|
@@ -59,13 +66,17 @@ export class RenownCredentialProcessor extends RelationalDbProcessor {
|
|
|
59
66
|
break;
|
|
60
67
|
}
|
|
61
68
|
case "UPDATE_CREDENTIAL_SUBJECT": {
|
|
62
|
-
|
|
63
|
-
|
|
69
|
+
// Access the updated state to get the synced vcPayload
|
|
70
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
71
|
+
const state = (strand.state)?.global;
|
|
72
|
+
if (state && existingCredential) {
|
|
64
73
|
await this.relationalDb
|
|
65
74
|
.updateTable("renown_credential")
|
|
66
75
|
.set({
|
|
67
|
-
credential_subject:
|
|
76
|
+
credential_subject: state.credentialSubject || null,
|
|
77
|
+
vc_payload: state.vcPayload || null, // Sync vcPayload with updated credentialSubject
|
|
68
78
|
jwt: null, // Clear JWT when content changes
|
|
79
|
+
jwt_verified: false, // Mark as unverified since content changed
|
|
69
80
|
updated_at: new Date(),
|
|
70
81
|
})
|
|
71
82
|
.where("document_id", "=", documentId)
|
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
export async function up(db) {
|
|
2
2
|
await down(db);
|
|
3
|
-
// Create renown_credential table
|
|
3
|
+
// Create renown_credential table with flexible VC schema support
|
|
4
4
|
await db.schema
|
|
5
5
|
.createTable("renown_credential")
|
|
6
6
|
.addColumn("document_id", "varchar(255)")
|
|
7
|
-
.addColumn("
|
|
7
|
+
.addColumn("jwt", "text") // JWT token containing the VC
|
|
8
|
+
.addColumn("jwt_verified", "boolean", (col) => col.notNull().defaultTo(false))
|
|
9
|
+
.addColumn("vc_payload", "text") // Complete VC JSON object extracted from JWT
|
|
10
|
+
.addColumn("context", "text") // JSON array - extracted for convenience
|
|
8
11
|
.addColumn("credential_id", "varchar(255)")
|
|
9
|
-
.addColumn("type", "text") // JSON array
|
|
10
|
-
.addColumn("issuer", "varchar(255)"
|
|
11
|
-
.addColumn("issuance_date", "timestamp"
|
|
12
|
-
.addColumn("credential_subject", "text"
|
|
12
|
+
.addColumn("type", "text") // JSON array - extracted for convenience
|
|
13
|
+
.addColumn("issuer", "varchar(255)") // Now nullable to support any VC structure
|
|
14
|
+
.addColumn("issuance_date", "timestamp") // Now nullable
|
|
15
|
+
.addColumn("credential_subject", "text") // JSON object - now nullable
|
|
13
16
|
.addColumn("expiration_date", "timestamp")
|
|
14
17
|
.addColumn("credential_status_id", "varchar(255)")
|
|
15
18
|
.addColumn("credential_status_type", "varchar(255)")
|
|
16
19
|
.addColumn("credential_status_purpose", "varchar(255)")
|
|
17
20
|
.addColumn("credential_status_list_index", "varchar(255)")
|
|
18
21
|
.addColumn("credential_status_list_credential", "text")
|
|
19
|
-
.addColumn("jwt", "text")
|
|
20
22
|
.addColumn("revoked", "boolean", (col) => col.notNull().defaultTo(false))
|
|
21
23
|
.addColumn("revoked_at", "timestamp")
|
|
22
24
|
.addColumn("revocation_reason", "text")
|
|
@@ -3,19 +3,21 @@ export type Generated<T> = T extends ColumnType<infer S, infer I, infer U> ? Col
|
|
|
3
3
|
export type Timestamp = ColumnType<Date, Date | string, Date | string>;
|
|
4
4
|
export interface RenownCredential {
|
|
5
5
|
document_id: string;
|
|
6
|
-
|
|
6
|
+
jwt: string | null;
|
|
7
|
+
jwt_verified: boolean;
|
|
8
|
+
vc_payload: string | null;
|
|
9
|
+
context: string | null;
|
|
7
10
|
credential_id: string | null;
|
|
8
|
-
type: string;
|
|
9
|
-
issuer: string;
|
|
10
|
-
issuance_date: Timestamp;
|
|
11
|
-
credential_subject: string;
|
|
11
|
+
type: string | null;
|
|
12
|
+
issuer: string | null;
|
|
13
|
+
issuance_date: Timestamp | null;
|
|
14
|
+
credential_subject: string | null;
|
|
12
15
|
expiration_date: Timestamp | null;
|
|
13
16
|
credential_status_id: string | null;
|
|
14
17
|
credential_status_type: string | null;
|
|
15
18
|
credential_status_purpose: string | null;
|
|
16
19
|
credential_status_list_index: string | null;
|
|
17
20
|
credential_status_list_credential: string | null;
|
|
18
|
-
jwt: string | null;
|
|
19
21
|
revoked: boolean;
|
|
20
22
|
revoked_at: Timestamp | null;
|
|
21
23
|
revocation_reason: string | null;
|
package/dist/style.css
CHANGED
|
@@ -61,6 +61,7 @@
|
|
|
61
61
|
--color-blue-900: oklch(37.9% 0.146 265.522);
|
|
62
62
|
--color-indigo-50: oklch(96.2% 0.018 272.314);
|
|
63
63
|
--color-indigo-800: oklch(39.8% 0.195 277.366);
|
|
64
|
+
--color-purple-50: oklch(97.7% 0.014 308.299);
|
|
64
65
|
--color-purple-800: oklch(43.8% 0.218 303.724);
|
|
65
66
|
--color-purple-900: oklch(38.1% 0.176 304.987);
|
|
66
67
|
--color-pink-400: oklch(71.8% 0.202 349.761);
|
|
@@ -361,6 +362,9 @@
|
|
|
361
362
|
.h-24 {
|
|
362
363
|
height: calc(var(--spacing) * 24);
|
|
363
364
|
}
|
|
365
|
+
.max-h-96 {
|
|
366
|
+
max-height: calc(var(--spacing) * 96);
|
|
367
|
+
}
|
|
364
368
|
.min-h-screen {
|
|
365
369
|
min-height: 100vh;
|
|
366
370
|
}
|
|
@@ -526,6 +530,9 @@
|
|
|
526
530
|
.bg-green-100 {
|
|
527
531
|
background-color: var(--color-green-100);
|
|
528
532
|
}
|
|
533
|
+
.bg-purple-50 {
|
|
534
|
+
background-color: var(--color-purple-50);
|
|
535
|
+
}
|
|
529
536
|
.bg-red-50 {
|
|
530
537
|
background-color: var(--color-red-50);
|
|
531
538
|
}
|
|
@@ -12,21 +12,25 @@ export const schema = gql `
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
type RenownCredentialState {
|
|
15
|
-
"
|
|
16
|
-
|
|
15
|
+
"JWT token containing the Verifiable Credential"
|
|
16
|
+
jwt: String
|
|
17
|
+
jwtVerified: Boolean
|
|
18
|
+
|
|
19
|
+
"Complete VC Payload - extracted from JWT for convenience and flexibility"
|
|
20
|
+
vcPayload: String
|
|
21
|
+
|
|
22
|
+
"W3C VC Common Fields - extracted for querying convenience, may be null for non-standard VCs"
|
|
23
|
+
context: [String!]
|
|
17
24
|
id: String
|
|
18
|
-
type: [String!]
|
|
19
|
-
issuer: String
|
|
20
|
-
issuanceDate: DateTime
|
|
21
|
-
credentialSubject: String
|
|
25
|
+
type: [String!]
|
|
26
|
+
issuer: String
|
|
27
|
+
issuanceDate: DateTime
|
|
28
|
+
credentialSubject: String
|
|
22
29
|
|
|
23
30
|
"W3C VC Optional Fields"
|
|
24
31
|
expirationDate: DateTime
|
|
25
32
|
credentialStatus: CredentialStatus
|
|
26
33
|
|
|
27
|
-
"JWT Representation"
|
|
28
|
-
jwt: String
|
|
29
|
-
|
|
30
34
|
"Revocation tracking"
|
|
31
35
|
revoked: Boolean
|
|
32
36
|
revokedAt: DateTime
|
|
@@ -82,13 +86,7 @@ export const schema = gql `
|
|
|
82
86
|
Module: Manager
|
|
83
87
|
"""
|
|
84
88
|
input RenownCredential_InitInput {
|
|
85
|
-
|
|
86
|
-
id: String
|
|
87
|
-
type: [String!]
|
|
88
|
-
issuer: String!
|
|
89
|
-
issuanceDate: DateTime!
|
|
90
|
-
credentialSubject: String!
|
|
91
|
-
expirationDate: DateTime
|
|
89
|
+
jwt: String!
|
|
92
90
|
}
|
|
93
91
|
input RenownCredential_RevokeInput {
|
|
94
92
|
revokedAt: DateTime!
|
|
@@ -10,9 +10,12 @@ const mapToUser = (user) => ({
|
|
|
10
10
|
});
|
|
11
11
|
const mapToCredential = (credential) => ({
|
|
12
12
|
documentId: credential.document_id,
|
|
13
|
+
jwt: credential.jwt,
|
|
14
|
+
jwtVerified: credential.jwt_verified,
|
|
15
|
+
vcPayload: credential.vc_payload,
|
|
13
16
|
credentialId: credential.credential_id,
|
|
14
|
-
context: JSON.parse(credential.context),
|
|
15
|
-
type: JSON.parse(credential.type),
|
|
17
|
+
context: credential.context ? JSON.parse(credential.context) : null,
|
|
18
|
+
type: credential.type ? JSON.parse(credential.type) : null,
|
|
16
19
|
issuer: credential.issuer,
|
|
17
20
|
issuanceDate: credential.issuance_date,
|
|
18
21
|
credentialSubject: credential.credential_subject,
|
|
@@ -30,7 +33,6 @@ const mapToCredential = (credential) => ({
|
|
|
30
33
|
statusListCredential: credential.credential_status_list_credential,
|
|
31
34
|
}
|
|
32
35
|
: null,
|
|
33
|
-
jwt: credential.jwt,
|
|
34
36
|
revoked: credential.revoked,
|
|
35
37
|
revokedAt: credential.revoked_at,
|
|
36
38
|
revocationReason: credential.revocation_reason,
|
|
@@ -28,15 +28,17 @@ export const schema = gql `
|
|
|
28
28
|
|
|
29
29
|
type ReadRenownCredential {
|
|
30
30
|
documentId: String!
|
|
31
|
+
jwt: String
|
|
32
|
+
jwtVerified: Boolean!
|
|
33
|
+
vcPayload: String
|
|
31
34
|
credentialId: String
|
|
32
|
-
context: [String!]
|
|
33
|
-
type: [String!]
|
|
34
|
-
issuer: String
|
|
35
|
-
issuanceDate: DateTime
|
|
36
|
-
credentialSubject: String
|
|
35
|
+
context: [String!]
|
|
36
|
+
type: [String!]
|
|
37
|
+
issuer: String
|
|
38
|
+
issuanceDate: DateTime
|
|
39
|
+
credentialSubject: String
|
|
37
40
|
expirationDate: DateTime
|
|
38
41
|
credentialStatus: ReadCredentialStatus
|
|
39
|
-
jwt: String
|
|
40
42
|
revoked: Boolean!
|
|
41
43
|
revokedAt: DateTime
|
|
42
44
|
revocationReason: String
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@powerhousedao/renown-package",
|
|
3
3
|
"description": "",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.30",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
@@ -62,12 +62,14 @@
|
|
|
62
62
|
"./style.css": "./dist/style.css"
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@powerhousedao/builder-tools": "staging",
|
|
66
|
-
"@powerhousedao/common": "staging",
|
|
67
|
-
"@powerhousedao/design-system": "staging",
|
|
65
|
+
"@powerhousedao/builder-tools": "5.0.0-staging.30",
|
|
66
|
+
"@powerhousedao/common": "5.0.0-staging.30",
|
|
67
|
+
"@powerhousedao/design-system": "5.0.0-staging.30",
|
|
68
68
|
"@powerhousedao/document-engineering": "^1.37.0",
|
|
69
|
-
"@powerhousedao/vetra": "staging",
|
|
70
|
-
"
|
|
69
|
+
"@powerhousedao/vetra": "5.0.0-staging.30",
|
|
70
|
+
"did-jwt": "^8.0.18",
|
|
71
|
+
"did-jwt-vc": "^4.0.16",
|
|
72
|
+
"document-model": "5.0.0-staging.30",
|
|
71
73
|
"graphql": "^16.10.0",
|
|
72
74
|
"graphql-tag": "^2.12.6",
|
|
73
75
|
"kysely": "^0.28.7",
|
|
@@ -79,13 +81,13 @@
|
|
|
79
81
|
"@electric-sql/pglite": "^0.2.12",
|
|
80
82
|
"@eslint/js": "^9.22.0",
|
|
81
83
|
"@powerhousedao/analytics-engine-core": "^0.5.0",
|
|
82
|
-
"@powerhousedao/codegen": "staging",
|
|
83
|
-
"@powerhousedao/ph-cli": "staging",
|
|
84
|
-
"@powerhousedao/reactor-api": "staging",
|
|
85
|
-
"@powerhousedao/reactor-browser": "staging",
|
|
86
|
-
"@powerhousedao/reactor-local": "staging",
|
|
87
|
-
"@powerhousedao/scalars": "staging",
|
|
88
|
-
"@powerhousedao/switchboard": "staging",
|
|
84
|
+
"@powerhousedao/codegen": "5.0.0-staging.30",
|
|
85
|
+
"@powerhousedao/ph-cli": "5.0.0-staging.30",
|
|
86
|
+
"@powerhousedao/reactor-api": "5.0.0-staging.30",
|
|
87
|
+
"@powerhousedao/reactor-browser": "5.0.0-staging.30",
|
|
88
|
+
"@powerhousedao/reactor-local": "5.0.0-staging.30",
|
|
89
|
+
"@powerhousedao/scalars": "1.33.1-staging.5",
|
|
90
|
+
"@powerhousedao/switchboard": "5.0.0-staging.30",
|
|
89
91
|
"@semantic-release/changelog": "^6.0.3",
|
|
90
92
|
"@semantic-release/git": "^10.0.1",
|
|
91
93
|
"@tailwindcss/cli": "^4.0.15",
|
|
@@ -93,7 +95,7 @@
|
|
|
93
95
|
"@types/node": "^22.13.11",
|
|
94
96
|
"@types/react": "^18.3.19",
|
|
95
97
|
"@vitejs/plugin-react": "^4.3.4",
|
|
96
|
-
"document-drive": "staging",
|
|
98
|
+
"document-drive": "5.0.0-staging.30",
|
|
97
99
|
"eslint": "^9.22.0",
|
|
98
100
|
"eslint-plugin-react": "^7.37.4",
|
|
99
101
|
"eslint-plugin-react-hooks": "^5.2.0",
|