gdc-common-utils-ts 2.7.1 → 2.7.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.
@@ -47,6 +47,22 @@ export declare const ConsentDecisions: Readonly<{
47
47
  readonly Deny: "deny";
48
48
  }>;
49
49
  export type ConsentDecision = typeof ConsentDecisions[keyof typeof ConsentDecisions];
50
+ /**
51
+ * Canonical FHIR R5 Consent lifecycle states.
52
+ *
53
+ * `draft` is the only state used for a professional permission request. A
54
+ * draft is carried to the controller for review and must never participate in
55
+ * authorization evaluation. Only `active` consent rules can grant access.
56
+ */
57
+ export declare const ConsentStatuses: Readonly<{
58
+ readonly Draft: "draft";
59
+ readonly Active: "active";
60
+ readonly Inactive: "inactive";
61
+ readonly NotDone: "not-done";
62
+ readonly EnteredInError: "entered-in-error";
63
+ readonly Unknown: "unknown";
64
+ }>;
65
+ export type ConsentStatus = typeof ConsentStatuses[keyof typeof ConsentStatuses];
50
66
  /**
51
67
  * Defines the structured, query-optimized format for storing a single, atomic consent rule
52
68
  * in the vault (e.g., Firestore, CouchDB).
@@ -67,6 +83,8 @@ export interface ConsentRule {
67
83
  * Value MUST be "org.hl7.fhir.api".
68
84
  */
69
85
  '@context': 'org.hl7.fhir.api';
86
+ /** FHIR Consent lifecycle state; authorization evaluators accept only `active`. */
87
+ 'Consent.status'?: ConsentStatus;
70
88
  /**
71
89
  * The decision of the rule: permit or deny.
72
90
  * Derived from the `org.hl7.fhir.api.Consent.decision` claim.
@@ -48,3 +48,18 @@ export const ConsentDecisions = Object.freeze({
48
48
  Permit: 'permit',
49
49
  Deny: 'deny',
50
50
  });
51
+ /**
52
+ * Canonical FHIR R5 Consent lifecycle states.
53
+ *
54
+ * `draft` is the only state used for a professional permission request. A
55
+ * draft is carried to the controller for review and must never participate in
56
+ * authorization evaluation. Only `active` consent rules can grant access.
57
+ */
58
+ export const ConsentStatuses = Object.freeze({
59
+ Draft: 'draft',
60
+ Active: 'active',
61
+ Inactive: 'inactive',
62
+ NotDone: 'not-done',
63
+ EnteredInError: 'entered-in-error',
64
+ Unknown: 'unknown',
65
+ });
@@ -3,7 +3,7 @@
3
3
  * - Read `ARCHITECTURE.md` and `CONTRIBUTING.md` before changing this module.
4
4
  * - This file owns only the typed editor for one staged Consent entry.
5
5
  */
6
- import { type ConsentDecision } from '../models/consent-rule';
6
+ import { type ConsentDecision, type ConsentStatus } from '../models/consent-rule';
7
7
  import { BundleEntryEditor } from './bundle-entry-editor';
8
8
  /**
9
9
  * Typed editor for one Consent permission staged inside a Bundle.
@@ -17,6 +17,8 @@ export declare class ConsentEntryEditor extends BundleEntryEditor {
17
17
  ensureIdentifier(): string;
18
18
  setSubject(value?: string | null): this;
19
19
  getSubject(): string | undefined;
20
+ setStatus(value?: ConsentStatus | null): this;
21
+ getStatus(): string | undefined;
20
22
  setDecision(value?: ConsentDecision | null): this;
21
23
  getDecision(): string | undefined;
22
24
  setActorIdentifierList(values: readonly string[]): this;
@@ -43,6 +43,8 @@ export class ConsentEntryEditor extends BundleEntryEditor {
43
43
  }
44
44
  setSubject(value) { return this.setOptionalText(ClaimConsent.subject, value); }
45
45
  getSubject() { return this.getOptionalText(ClaimConsent.subject); }
46
+ setStatus(value) { return this.setOptionalText(ClaimConsent.status, value); }
47
+ getStatus() { return this.getOptionalText(ClaimConsent.status); }
46
48
  setDecision(value) { return this.setOptionalText(ClaimConsent.decision, value); }
47
49
  getDecision() { return this.getOptionalText(ClaimConsent.decision); }
48
50
  setActorIdentifierList(values) { return this.setList(ClaimConsent.actorIdentifier, values); }
@@ -197,6 +197,7 @@ export declare function resolveConsentActor(actor: ConsentActorDescriptor): Reso
197
197
  *
198
198
  * A rule is active when:
199
199
  * - it matches the requested subject when one is provided
200
+ * - `Consent.status` is absent for legacy compatibility or is exactly `active`
200
201
  * - `Consent.period-start` is absent or already effective
201
202
  * - `Consent.period-end` is absent or still in the future
202
203
  *
@@ -1,5 +1,5 @@
1
1
  // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
- import { ClaimConsent } from '../models/consent-rule.js';
2
+ import { ClaimConsent, ConsentStatuses } from '../models/consent-rule.js';
3
3
  import { assignCidToClaimsId } from './fhir-cid.js';
4
4
  /**
5
5
  * Normalizes a phone string into a compact token form.
@@ -512,6 +512,7 @@ export function resolveConsentActor(actor) {
512
512
  *
513
513
  * A rule is active when:
514
514
  * - it matches the requested subject when one is provided
515
+ * - `Consent.status` is absent for legacy compatibility or is exactly `active`
515
516
  * - `Consent.period-start` is absent or already effective
516
517
  * - `Consent.period-end` is absent or still in the future
517
518
  *
@@ -523,6 +524,9 @@ export function isConsentRuleActive(rule, options = {}) {
523
524
  if (options.subject && String(readConsentRuleClaim(rule, ClaimConsent.subject) || '').trim() !== String(options.subject || '').trim()) {
524
525
  return false;
525
526
  }
527
+ const status = String(readConsentRuleClaim(rule, ClaimConsent.status) || '').trim();
528
+ if (status && status !== ConsentStatuses.Active)
529
+ return false;
526
530
  const now = options.now instanceof Date
527
531
  ? options.now.getTime()
528
532
  : options.now
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdc-common-utils-ts",
3
- "version": "2.7.1",
3
+ "version": "2.7.2",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },