@absolutejs/auth 0.27.0-beta.7 → 0.27.0-beta.8

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.
@@ -2,14 +2,18 @@ import type { AuditEvent, AuditSink } from './types';
2
2
  export type AuditIntegrity = {
3
3
  hash: string;
4
4
  previousHash: string;
5
+ writerId?: string;
5
6
  };
6
7
  export type AuditChainResult = {
7
8
  brokenAt?: number;
8
9
  ok: boolean;
9
10
  };
10
- export declare const createTamperEvidentSink: ({ secret, sink }: {
11
+ export declare const createTamperEvidentSink: ({ loadWriterHead, secret, seedScanLimit, sink, writerId }: {
12
+ loadWriterHead?: (writerId: string) => Promise<string | undefined> | string | undefined;
11
13
  secret?: string;
14
+ seedScanLimit?: number;
12
15
  sink: AuditSink;
16
+ writerId?: string;
13
17
  }) => AuditSink;
14
18
  export declare const hashAuditEvent: (event: AuditEvent, previousHash: string, secret?: string) => Promise<string>;
15
19
  export declare const verifyAuditChain: (events: AuditEvent[], secret?: string) => Promise<AuditChainResult>;
package/dist/index.js CHANGED
@@ -18710,6 +18710,7 @@ var INTEGRITY_KEY = "__integrity";
18710
18710
  var GENESIS = "";
18711
18711
  var HEX_RADIX2 = 16;
18712
18712
  var HEX_PAD = 2;
18713
+ var DEFAULT_SEED_SCAN_LIMIT = 1000;
18713
18714
  var encoder = new TextEncoder;
18714
18715
  var toHex = (buffer) => [...new Uint8Array(buffer)].map((byte) => byte.toString(HEX_RADIX2).padStart(HEX_PAD, "0")).join("");
18715
18716
  var sha256Hex = async (message) => toHex(await crypto.subtle.digest("SHA-256", encoder.encode(message)));
@@ -18740,15 +18741,31 @@ var brokenAt = (index) => {
18740
18741
  return result;
18741
18742
  };
18742
18743
  var createTamperEvidentSink = ({
18744
+ loadWriterHead,
18743
18745
  secret,
18744
- sink
18746
+ seedScanLimit = DEFAULT_SEED_SCAN_LIMIT,
18747
+ sink,
18748
+ writerId
18745
18749
  }) => {
18750
+ const chainWriterId = writerId ?? crypto.randomUUID();
18751
+ const isResuming = writerId !== undefined;
18746
18752
  let lastHash;
18753
+ let seeded = false;
18747
18754
  const seed = async () => {
18748
- if (lastHash !== undefined)
18755
+ if (seeded)
18749
18756
  return;
18750
- const [recent] = await sink.list?.({ limit: 1 }) ?? [];
18751
- lastHash = recent ? readIntegrity(recent)?.hash ?? GENESIS : GENESIS;
18757
+ seeded = true;
18758
+ if (!isResuming) {
18759
+ lastHash = GENESIS;
18760
+ return;
18761
+ }
18762
+ if (loadWriterHead) {
18763
+ lastHash = await loadWriterHead(chainWriterId) ?? GENESIS;
18764
+ return;
18765
+ }
18766
+ const recent = await sink.list?.({ limit: seedScanLimit }) ?? [];
18767
+ const head = recent.find((event) => readIntegrity(event)?.writerId === chainWriterId);
18768
+ lastHash = head ? readIntegrity(head)?.hash ?? GENESIS : GENESIS;
18752
18769
  };
18753
18770
  return {
18754
18771
  list: sink.list,
@@ -18757,7 +18774,11 @@ var createTamperEvidentSink = ({
18757
18774
  const previousHash = lastHash ?? GENESIS;
18758
18775
  const hash = await hashAuditEvent(event, previousHash, secret);
18759
18776
  lastHash = hash;
18760
- const integrity = { hash, previousHash };
18777
+ const integrity = {
18778
+ hash,
18779
+ previousHash,
18780
+ writerId: chainWriterId
18781
+ };
18761
18782
  await sink.append({
18762
18783
  ...event,
18763
18784
  metadata: { ...event.metadata, [INTEGRITY_KEY]: integrity }
@@ -18773,17 +18794,19 @@ var hashAuditEvent = async (event, previousHash, secret) => {
18773
18794
  return secret === undefined ? sha256Hex(message) : hmacSha256Hex(secret, message);
18774
18795
  };
18775
18796
  var verifyAuditChain = async (events, secret) => {
18776
- let previousHash = GENESIS;
18797
+ const heads = new Map;
18777
18798
  for (let index = 0;index < events.length; index += 1) {
18778
18799
  const event = events[index];
18779
18800
  if (event === undefined)
18780
18801
  return brokenAt(index);
18781
18802
  const integrity = readIntegrity(event);
18803
+ const chain = integrity?.writerId ?? GENESIS;
18804
+ const previousHash = heads.get(chain) ?? GENESIS;
18782
18805
  const expected = await hashAuditEvent(event, previousHash, secret);
18783
18806
  if (integrity === undefined || integrity.previousHash !== previousHash || integrity.hash !== expected) {
18784
18807
  return brokenAt(index);
18785
18808
  }
18786
- previousHash = integrity.hash;
18809
+ heads.set(chain, integrity.hash);
18787
18810
  }
18788
18811
  const valid = { ok: true };
18789
18812
  return valid;
@@ -20976,5 +20999,5 @@ export {
20976
20999
  AuthIdentityConflictError
20977
21000
  };
20978
21001
 
20979
- //# debugId=580D3E8ACE9EF4E864756E2164756E21
21002
+ //# debugId=B234E4311897F15C64756E2164756E21
20980
21003
  //# sourceMappingURL=index.js.map