@researchdatabox/sails-hook-redbox-storage-mongo 5.0.3 → 5.0.4-beta.12498

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
@@ -24,6 +24,47 @@ This package provides the MongoDB-backed storage service, models, and config reg
24
24
  - The storage models use the Sails datastore named `redboxStorage`
25
25
  - Datastore connection details still live in the host portal’s Sails config
26
26
 
27
+ ## Record revision migration
28
+
29
+ This hook registers the restart-safe
30
+ `@researchdatabox/sails-hook-redbox-storage-mongo:20260823T000000-backfill-record-revisions`
31
+ migration. It installs the initial server-owned revision on active records and
32
+ the revision plus `deleted` lifecycle state on legacy tombstones. It does not
33
+ touch record metadata, workflow, authorization, `lastSaveDate`, or search
34
+ documents.
35
+
36
+ Run an upgrade with exactly one lifting portal instance, let migrations finish,
37
+ and only then start the remaining instances. The repository migration runner
38
+ has no distributed migration lock. Back up the database first; do not use
39
+ `REDBOX_SKIP_MIGRATIONS=true` for a strict-concurrency rollout.
40
+
41
+ ## Storage concurrency capability
42
+
43
+ Strict record types require a storage adapter to expose `getCapabilities()` and
44
+ return the supported `recordConcurrency` version token from
45
+ `@researchdatabox/redbox-core`. An absent method, absent field, unknown version,
46
+ or a non-Mongo dialect without native atomic operations is unsupported and
47
+ fails closed.
48
+
49
+ The capability covers these adapter methods:
50
+
51
+ - `create(..., options?)`: strips client revision and initializes a server revision;
52
+ - `updateMeta(..., options?)`: atomic active compare-and-set plus increment;
53
+ - `removeActiveRecord(..., options?)`: atomic conditional removal returning the removed state;
54
+ - `updateTombstone(..., options?)`: atomic restore/purge claim plus increment;
55
+ - `removeTombstone(..., options?)`: atomic conditional restore finalization/purge.
56
+
57
+ Every existing signature keeps its optional concurrency options last for source
58
+ compatibility. A supplied `expectedRevision` must always be honored. A
59
+ certified no-match returns `not-applied` with a bounded
60
+ `nonApplicationReason`; a thrown or unrecognized fact after dispatch returns
61
+ `unknown`. Adapters must never fall back to an OID-only Waterline success path
62
+ after advertising strict capability.
63
+
64
+ Hook-provided adapters must verify these guarantees against their real
65
+ datastore/dialect before declaring capability. The bundled Mongo adapter does
66
+ so in `test/integration/MongoStorageConcurrency.integration.test.ts`.
67
+
27
68
  ## Pagination regression tests
28
69
 
29
70
  Record and deleted-record lists append `_id` to the requested sort so equal
@@ -12,6 +12,7 @@ export declare const storage: {
12
12
  'metaMetadata.lastSaveDate'?: undefined;
13
13
  redboxOid?: undefined;
14
14
  };
15
+ unique?: undefined;
15
16
  } | {
16
17
  key: {
17
18
  harvestId: number;
@@ -23,6 +24,7 @@ export declare const storage: {
23
24
  'metaMetadata.lastSaveDate'?: undefined;
24
25
  redboxOid?: undefined;
25
26
  };
27
+ unique?: undefined;
26
28
  } | {
27
29
  key: {
28
30
  dateCreated: number;
@@ -34,6 +36,7 @@ export declare const storage: {
34
36
  'metaMetadata.lastSaveDate'?: undefined;
35
37
  redboxOid?: undefined;
36
38
  };
39
+ unique?: undefined;
37
40
  } | {
38
41
  key: {
39
42
  lastSaveDate: number;
@@ -45,6 +48,7 @@ export declare const storage: {
45
48
  'metaMetadata.lastSaveDate'?: undefined;
46
49
  redboxOid?: undefined;
47
50
  };
51
+ unique?: undefined;
48
52
  } | {
49
53
  key: {
50
54
  'metaMetadata.brandId': number;
@@ -56,6 +60,7 @@ export declare const storage: {
56
60
  'metaMetadata.lastSaveDate'?: undefined;
57
61
  redboxOid?: undefined;
58
62
  };
63
+ unique?: undefined;
59
64
  } | {
60
65
  key: {
61
66
  'metaMetadata.type': number;
@@ -67,6 +72,7 @@ export declare const storage: {
67
72
  'metaMetadata.lastSaveDate'?: undefined;
68
73
  redboxOid?: undefined;
69
74
  };
75
+ unique?: undefined;
70
76
  } | {
71
77
  key: {
72
78
  'metaMetadata.createdOn': number;
@@ -78,6 +84,7 @@ export declare const storage: {
78
84
  'metaMetadata.lastSaveDate'?: undefined;
79
85
  redboxOid?: undefined;
80
86
  };
87
+ unique?: undefined;
81
88
  } | {
82
89
  key: {
83
90
  'metaMetadata.lastSaveDate': number;
@@ -89,6 +96,7 @@ export declare const storage: {
89
96
  'metaMetadata.createdOn'?: undefined;
90
97
  redboxOid?: undefined;
91
98
  };
99
+ unique?: undefined;
92
100
  } | {
93
101
  key: {
94
102
  redboxOid: number;
@@ -100,6 +108,50 @@ export declare const storage: {
100
108
  'metaMetadata.createdOn'?: undefined;
101
109
  'metaMetadata.lastSaveDate'?: undefined;
102
110
  };
111
+ unique: boolean;
103
112
  })[];
113
+ deletedRecordIndices: ({
114
+ key: {
115
+ redboxOid: number;
116
+ lifecycleState?: undefined;
117
+ 'lifecycleOperation.requestId'?: undefined;
118
+ 'deletedRecordMetadata.metaMetadata.brandId'?: undefined;
119
+ brandId?: undefined;
120
+ };
121
+ unique: boolean;
122
+ } | {
123
+ key: {
124
+ lifecycleState: number;
125
+ 'lifecycleOperation.requestId': number;
126
+ redboxOid?: undefined;
127
+ 'deletedRecordMetadata.metaMetadata.brandId'?: undefined;
128
+ brandId?: undefined;
129
+ };
130
+ unique?: undefined;
131
+ } | {
132
+ key: {
133
+ 'deletedRecordMetadata.metaMetadata.brandId': number;
134
+ redboxOid: number;
135
+ lifecycleState?: undefined;
136
+ 'lifecycleOperation.requestId'?: undefined;
137
+ brandId?: undefined;
138
+ };
139
+ unique?: undefined;
140
+ } | {
141
+ key: {
142
+ brandId: number;
143
+ redboxOid: number;
144
+ lifecycleState?: undefined;
145
+ 'lifecycleOperation.requestId'?: undefined;
146
+ 'deletedRecordMetadata.metaMetadata.brandId'?: undefined;
147
+ };
148
+ unique?: undefined;
149
+ })[];
150
+ recordIdentityIndices: {
151
+ key: {
152
+ redboxOid: number;
153
+ };
154
+ unique: boolean;
155
+ }[];
104
156
  };
105
157
  };
@@ -17,9 +17,24 @@ exports.storage = {
17
17
  { key: { 'metaMetadata.createdOn': -1 } },
18
18
  { key: { 'metaMetadata.lastSaveDate': 1 } },
19
19
  { key: { 'metaMetadata.lastSaveDate': -1 } },
20
- { key: { redboxOid: 1 } },
21
- { key: { redboxOid: -1 } },
20
+ // Active create/restore classification relies on duplicate-key facts;
21
+ // keep the native Mongo index explicit as well as the Waterline model
22
+ // constraint. One single-field index serves both scan directions.
23
+ { key: { redboxOid: 1 }, unique: true },
22
24
  ],
25
+ // Every tombstone lookup starts from the OID, so it leads the compound
26
+ // keys; the brand is a filter on the single document the OID selects. The
27
+ // lifecycle key supports scanning for interrupted staged operations.
28
+ deletedRecordIndices: [
29
+ { key: { redboxOid: 1 }, unique: true },
30
+ { key: { lifecycleState: 1, 'lifecycleOperation.requestId': 1 } },
31
+ { key: { 'deletedRecordMetadata.metaMetadata.brandId': 1, redboxOid: 1 } },
32
+ { key: { brandId: 1, redboxOid: 1 } },
33
+ ],
34
+ // A committed incarnation is intentionally never purged. The only safe
35
+ // exception is an unused create reservation released after a certified
36
+ // non-write and authoritative empty-state checks.
37
+ recordIdentityIndices: [{ key: { redboxOid: 1 }, unique: true }],
23
38
  },
24
39
  };
25
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmFnZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb25maWcvc3RvcmFnZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBYSxRQUFBLE9BQU8sR0FBRztJQUNyQixXQUFXLEVBQUUscUJBQXFCO0lBQ2xDLE9BQU8sRUFBRTtRQUNQLE9BQU8sRUFBRTtZQUNQLEVBQUUsR0FBRyxFQUFFLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ3pCLEVBQUUsR0FBRyxFQUFFLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBRSxzQkFBc0IsRUFBRSxDQUFDLEVBQUUsbUJBQW1CLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDNUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxXQUFXLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDM0IsRUFBRSxHQUFHLEVBQUUsRUFBRSxXQUFXLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUM1QixFQUFFLEdBQUcsRUFBRSxFQUFFLFlBQVksRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUM1QixFQUFFLEdBQUcsRUFBRSxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFO1lBQzdCLEVBQUUsR0FBRyxFQUFFLEVBQUUsc0JBQXNCLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDdEMsRUFBRSxHQUFHLEVBQUUsRUFBRSxtQkFBbUIsRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUNuQyxFQUFFLEdBQUcsRUFBRSxFQUFFLHdCQUF3QixFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ3hDLEVBQUUsR0FBRyxFQUFFLEVBQUUsd0JBQXdCLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUN6QyxFQUFFLEdBQUcsRUFBRSxFQUFFLDJCQUEyQixFQUFFLENBQUMsRUFBRSxFQUFFO1lBQzNDLEVBQUUsR0FBRyxFQUFFLEVBQUUsMkJBQTJCLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUM1QyxFQUFFLEdBQUcsRUFBRSxFQUFFLFNBQVMsRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUN6QixFQUFFLEdBQUcsRUFBRSxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFO1NBQzNCO0tBQ0Y7Q0FDRixDQUFDIn0=
40
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmFnZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb25maWcvc3RvcmFnZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBYSxRQUFBLE9BQU8sR0FBRztJQUNyQixXQUFXLEVBQUUscUJBQXFCO0lBQ2xDLE9BQU8sRUFBRTtRQUNQLE9BQU8sRUFBRTtZQUNQLEVBQUUsR0FBRyxFQUFFLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ3pCLEVBQUUsR0FBRyxFQUFFLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBRSxzQkFBc0IsRUFBRSxDQUFDLEVBQUUsbUJBQW1CLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDNUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxXQUFXLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDM0IsRUFBRSxHQUFHLEVBQUUsRUFBRSxXQUFXLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUM1QixFQUFFLEdBQUcsRUFBRSxFQUFFLFlBQVksRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUM1QixFQUFFLEdBQUcsRUFBRSxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFO1lBQzdCLEVBQUUsR0FBRyxFQUFFLEVBQUUsc0JBQXNCLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDdEMsRUFBRSxHQUFHLEVBQUUsRUFBRSxtQkFBbUIsRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUNuQyxFQUFFLEdBQUcsRUFBRSxFQUFFLHdCQUF3QixFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ3hDLEVBQUUsR0FBRyxFQUFFLEVBQUUsd0JBQXdCLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUN6QyxFQUFFLEdBQUcsRUFBRSxFQUFFLDJCQUEyQixFQUFFLENBQUMsRUFBRSxFQUFFO1lBQzNDLEVBQUUsR0FBRyxFQUFFLEVBQUUsMkJBQTJCLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUM1QyxzRUFBc0U7WUFDdEUsc0VBQXNFO1lBQ3RFLGtFQUFrRTtZQUNsRSxFQUFFLEdBQUcsRUFBRSxFQUFFLFNBQVMsRUFBRSxDQUFDLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO1NBQ3hDO1FBQ0QsdUVBQXVFO1FBQ3ZFLDBFQUEwRTtRQUMxRSxxRUFBcUU7UUFDckUsb0JBQW9CLEVBQUU7WUFDcEIsRUFBRSxHQUFHLEVBQUUsRUFBRSxTQUFTLEVBQUUsQ0FBQyxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtZQUN2QyxFQUFFLEdBQUcsRUFBRSxFQUFFLGNBQWMsRUFBRSxDQUFDLEVBQUUsOEJBQThCLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDakUsRUFBRSxHQUFHLEVBQUUsRUFBRSw0Q0FBNEMsRUFBRSxDQUFDLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQzFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxFQUFFLEVBQUU7U0FDdEM7UUFDRCx1RUFBdUU7UUFDdkUsdUVBQXVFO1FBQ3ZFLGtEQUFrRDtRQUNsRCxxQkFBcUIsRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQztLQUNqRTtDQUNGLENBQUMifQ==
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ import { storage } from './config/storage';
3
3
  import { record } from './config/record';
4
4
  import { MongoModels } from './models';
5
5
  import { ServiceExports } from './services';
6
+ import { registerRedboxMigrations } from './migrations';
6
7
  type RedboxStorageMongoHook = ((_sails: unknown) => SailsHook) & {
7
8
  registerRedboxModels: () => typeof MongoModels;
8
9
  registerRedboxServices: () => typeof ServiceExports;
@@ -10,6 +11,7 @@ type RedboxStorageMongoHook = ((_sails: unknown) => SailsHook) & {
10
11
  storage: typeof storage;
11
12
  record: typeof record;
12
13
  };
14
+ registerRedboxMigrations: typeof registerRedboxMigrations;
13
15
  ServiceExports: typeof ServiceExports;
14
16
  };
15
17
  declare const hook: RedboxStorageMongoHook;
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ const storage_1 = require("./config/storage");
3
3
  const record_1 = require("./config/record");
4
4
  const models_1 = require("./models");
5
5
  const services_1 = require("./services");
6
+ const migrations_1 = require("./migrations");
6
7
  const hook = ((_sails) => ({
7
8
  initialize(cb) {
8
9
  cb();
@@ -27,5 +28,6 @@ hook.registerRedboxConfig = function registerRedboxConfig() {
27
28
  };
28
29
  };
29
30
  hook.ServiceExports = services_1.ServiceExports;
31
+ hook.registerRedboxMigrations = migrations_1.registerRedboxMigrations;
30
32
  module.exports = hook;
31
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUNBLDhDQUEyQztBQUMzQyw0Q0FBeUM7QUFDekMscUNBQXVDO0FBQ3ZDLHlDQUE0QztBQVM1QyxNQUFNLElBQUksR0FBRyxDQUFDLENBQUMsTUFBZSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ2xDLFVBQVUsQ0FBQyxFQUF5QjtRQUNsQyxFQUFFLEVBQUUsQ0FBQztJQUNQLENBQUM7SUFDRCxNQUFNLEVBQUU7UUFDTixNQUFNLEVBQUUsRUFBRTtRQUNWLEtBQUssRUFBRSxFQUFFO0tBQ1Y7SUFDRCxTQUFTLEtBQUksQ0FBQztJQUNkLFFBQVEsRUFBRSxFQUFFO0NBQ2IsQ0FBQyxDQUEyQixDQUFDO0FBRTlCLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxTQUFTLG9CQUFvQjtJQUN2RCxPQUFPLG9CQUFXLENBQUM7QUFDckIsQ0FBQyxDQUFDO0FBRUYsSUFBSSxDQUFDLHNCQUFzQixHQUFHLFNBQVMsc0JBQXNCO0lBQzNELE9BQU8seUJBQWMsQ0FBQztBQUN4QixDQUFDLENBQUM7QUFFRixJQUFJLENBQUMsb0JBQW9CLEdBQUcsU0FBUyxvQkFBb0I7SUFDdkQsT0FBTztRQUNMLE9BQU8sRUFBUCxpQkFBTztRQUNQLE1BQU0sRUFBTixlQUFNO0tBQ1AsQ0FBQztBQUNKLENBQUMsQ0FBQztBQUVGLElBQUksQ0FBQyxjQUFjLEdBQUcseUJBQWMsQ0FBQztBQUVyQyxpQkFBUyxJQUFJLENBQUMifQ==
33
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUNBLDhDQUEyQztBQUMzQyw0Q0FBeUM7QUFDekMscUNBQXVDO0FBQ3ZDLHlDQUE0QztBQUM1Qyw2Q0FBd0Q7QUFVeEQsTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFDLE1BQWUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNsQyxVQUFVLENBQUMsRUFBeUI7UUFDbEMsRUFBRSxFQUFFLENBQUM7SUFDUCxDQUFDO0lBQ0QsTUFBTSxFQUFFO1FBQ04sTUFBTSxFQUFFLEVBQUU7UUFDVixLQUFLLEVBQUUsRUFBRTtLQUNWO0lBQ0QsU0FBUyxLQUFJLENBQUM7SUFDZCxRQUFRLEVBQUUsRUFBRTtDQUNiLENBQUMsQ0FBMkIsQ0FBQztBQUU5QixJQUFJLENBQUMsb0JBQW9CLEdBQUcsU0FBUyxvQkFBb0I7SUFDdkQsT0FBTyxvQkFBVyxDQUFDO0FBQ3JCLENBQUMsQ0FBQztBQUVGLElBQUksQ0FBQyxzQkFBc0IsR0FBRyxTQUFTLHNCQUFzQjtJQUMzRCxPQUFPLHlCQUFjLENBQUM7QUFDeEIsQ0FBQyxDQUFDO0FBRUYsSUFBSSxDQUFDLG9CQUFvQixHQUFHLFNBQVMsb0JBQW9CO0lBQ3ZELE9BQU87UUFDTCxPQUFPLEVBQVAsaUJBQU87UUFDUCxNQUFNLEVBQU4sZUFBTTtLQUNQLENBQUM7QUFDSixDQUFDLENBQUM7QUFFRixJQUFJLENBQUMsY0FBYyxHQUFHLHlCQUFjLENBQUM7QUFDckMsSUFBSSxDQUFDLHdCQUF3QixHQUFHLHFDQUF3QixDQUFDO0FBRXpELGlCQUFTLElBQUksQ0FBQyJ9
@@ -0,0 +1,5 @@
1
+ import type { RedboxMigration } from '@researchdatabox/redbox-core';
2
+ export * from './recordRevisionBackfill';
3
+ export declare const MigrationExports: RedboxMigration[];
4
+ /** Synchronous registry consumed by the generated ReDBox migration shim. */
5
+ export declare function registerRedboxMigrations(): RedboxMigration[];
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.MigrationExports = void 0;
18
+ exports.registerRedboxMigrations = registerRedboxMigrations;
19
+ const recordRevisionBackfill_1 = require("./recordRevisionBackfill");
20
+ __exportStar(require("./recordRevisionBackfill"), exports);
21
+ exports.MigrationExports = [recordRevisionBackfill_1.recordRevisionBackfillMigration];
22
+ /** Synchronous registry consumed by the generated ReDBox migration shim. */
23
+ function registerRedboxMigrations() {
24
+ return exports.MigrationExports;
25
+ }
26
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWlncmF0aW9ucy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7OztBQVFBLDREQUVDO0FBVEQscUVBQTJFO0FBRTNFLDJEQUF5QztBQUU1QixRQUFBLGdCQUFnQixHQUFzQixDQUFDLHdEQUErQixDQUFDLENBQUM7QUFFckYsNEVBQTRFO0FBQzVFLFNBQWdCLHdCQUF3QjtJQUN0QyxPQUFPLHdCQUFnQixDQUFDO0FBQzFCLENBQUMifQ==
@@ -0,0 +1,26 @@
1
+ import type { Db } from 'mongodb';
2
+ import { type RedboxMigration } from '@researchdatabox/redbox-core';
3
+ export declare const RECORD_REVISION_BACKFILL_MIGRATION_NAME = "@researchdatabox/sails-hook-redbox-storage-mongo:20260823T000000-backfill-record-revisions";
4
+ export declare const RECORD_REVISION_BACKFILL_BATCH_SIZE = 500;
5
+ export interface RecordRevisionBackfillStats {
6
+ activeUpdated: number;
7
+ tombstonesUpdated: number;
8
+ batches: number;
9
+ durationMs: number;
10
+ }
11
+ type MigrationLogger = Pick<Console, 'info' | 'error'>;
12
+ interface BackfillOptions {
13
+ batchSize?: number;
14
+ now?: () => number;
15
+ }
16
+ /**
17
+ * Restart-safe backfill. Only the new wrapper fields are written; record
18
+ * metadata, workflow, authorization, lastSaveDate, and search documents are
19
+ * deliberately absent from every update document.
20
+ *
21
+ * Each batch re-queries the documents that still need the backfill, so an
22
+ * interrupted run resumes simply by being run again.
23
+ */
24
+ export declare function backfillRecordRevisions(db: Db, recordCollectionName: string, tombstoneCollectionName: string, logger: MigrationLogger, options?: BackfillOptions): Promise<RecordRevisionBackfillStats>;
25
+ export declare const recordRevisionBackfillMigration: RedboxMigration;
26
+ export {};
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.recordRevisionBackfillMigration = exports.RECORD_REVISION_BACKFILL_BATCH_SIZE = exports.RECORD_REVISION_BACKFILL_MIGRATION_NAME = void 0;
4
+ exports.backfillRecordRevisions = backfillRecordRevisions;
5
+ const redbox_core_1 = require("@researchdatabox/redbox-core");
6
+ exports.RECORD_REVISION_BACKFILL_MIGRATION_NAME = '@researchdatabox/sails-hook-redbox-storage-mongo:20260823T000000-backfill-record-revisions';
7
+ exports.RECORD_REVISION_BACKFILL_BATCH_SIZE = 500;
8
+ /** Equality against `null` matches both a null value and an absent field. */
9
+ const MISSING_REVISION = { revision: null };
10
+ const MISSING_LIFECYCLE_STATE = { lifecycleState: null };
11
+ const PENDING = {
12
+ active: MISSING_REVISION,
13
+ tombstone: { $or: [MISSING_REVISION, MISSING_LIFECYCLE_STATE] },
14
+ };
15
+ const SAFE_FAILURE_CODES = new Set([
16
+ 'record-revision-backfill-no-progress',
17
+ 'record-revision-backfill-invalid-batch-size',
18
+ ]);
19
+ function safeFailureCode(error) {
20
+ const message = error instanceof Error ? error.message : '';
21
+ return SAFE_FAILURE_CODES.has(message) ? message : 'record-revision-backfill-failed';
22
+ }
23
+ async function backfillCollection(collection, kind, batchSize) {
24
+ const pending = PENDING[kind];
25
+ let updated = 0;
26
+ let batches = 0;
27
+ for (;;) {
28
+ const documents = await collection
29
+ .find(pending, { projection: { _id: 1, revision: 1, lifecycleState: 1 } })
30
+ .limit(batchSize)
31
+ .toArray();
32
+ if (documents.length === 0)
33
+ break;
34
+ const operations = documents.map(document => ({
35
+ updateOne: {
36
+ filter: { $and: [{ _id: document._id }, pending] },
37
+ // Evaluate the fallback against the value present when Mongo applies
38
+ // the update, not the earlier projected snapshot. This preserves a
39
+ // revision or lifecycle state installed by a concurrent/resumed run
40
+ // while still filling whichever sibling field remains absent.
41
+ update: [
42
+ {
43
+ $set: {
44
+ revision: { $ifNull: ['$revision', redbox_core_1.INITIAL_RECORD_REVISION] },
45
+ ...(kind === 'tombstone' ? { lifecycleState: { $ifNull: ['$lifecycleState', 'deleted'] } } : {}),
46
+ },
47
+ },
48
+ ],
49
+ },
50
+ }));
51
+ const result = await collection.bulkWrite(operations, { ordered: false });
52
+ updated += result.modifiedCount;
53
+ batches += 1;
54
+ // Guard against an unsupported dialect silently reporting success and
55
+ // looping forever. Another idempotent runner may legitimately have won the
56
+ // whole batch, so only a batch whose own documents are still pending is a
57
+ // genuine failure to progress.
58
+ if (result.modifiedCount === 0) {
59
+ const stillPending = await collection.countDocuments({ $and: [{ _id: { $in: documents.map(document => document._id) } }, pending] }, { limit: 1 });
60
+ if (stillPending > 0) {
61
+ throw new Error('record-revision-backfill-no-progress');
62
+ }
63
+ }
64
+ }
65
+ return { updated, batches };
66
+ }
67
+ /**
68
+ * Restart-safe backfill. Only the new wrapper fields are written; record
69
+ * metadata, workflow, authorization, lastSaveDate, and search documents are
70
+ * deliberately absent from every update document.
71
+ *
72
+ * Each batch re-queries the documents that still need the backfill, so an
73
+ * interrupted run resumes simply by being run again.
74
+ */
75
+ async function backfillRecordRevisions(db, recordCollectionName, tombstoneCollectionName, logger, options = {}) {
76
+ const now = options.now ?? Date.now;
77
+ const start = now();
78
+ const batchSize = options.batchSize ?? exports.RECORD_REVISION_BACKFILL_BATCH_SIZE;
79
+ try {
80
+ if (!Number.isSafeInteger(batchSize) || batchSize < 1 || batchSize > 10_000) {
81
+ throw new TypeError('record-revision-backfill-invalid-batch-size');
82
+ }
83
+ const active = await backfillCollection(db.collection(recordCollectionName), 'active', batchSize);
84
+ const tombstones = await backfillCollection(db.collection(tombstoneCollectionName), 'tombstone', batchSize);
85
+ const stats = {
86
+ activeUpdated: active.updated,
87
+ tombstonesUpdated: tombstones.updated,
88
+ batches: active.batches + tombstones.batches,
89
+ durationMs: Math.max(0, now() - start),
90
+ };
91
+ logger.info(`Record revision backfill complete: active=${stats.activeUpdated}, tombstones=${stats.tombstonesUpdated}, ` +
92
+ `batches=${stats.batches}, durationMs=${stats.durationMs}.`);
93
+ return stats;
94
+ }
95
+ catch (error) {
96
+ // The logged code stays bounded: a driver message can carry record detail,
97
+ // so only this migration's own codes are echoed. The original error travels
98
+ // as the thrown error's cause for the operator's stack trace.
99
+ const durationMs = Math.max(0, now() - start);
100
+ logger.error(`Record revision backfill failed: code=${safeFailureCode(error)}, durationMs=${durationMs}.`);
101
+ throw new Error('record-revision-backfill-failed', { cause: error });
102
+ }
103
+ }
104
+ exports.recordRevisionBackfillMigration = {
105
+ name: exports.RECORD_REVISION_BACKFILL_MIGRATION_NAME,
106
+ async up(params) {
107
+ const sails = params?.context;
108
+ if (!sails?.models?.record || !sails?.models?.deletedrecord) {
109
+ throw new Error('record-revision-backfill-models-unavailable');
110
+ }
111
+ const db = sails.models.record.getDatastore().manager;
112
+ await backfillRecordRevisions(db, sails.models.record.tableName, sails.models.deletedrecord.tableName, sails.log);
113
+ },
114
+ };
115
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVjb3JkUmV2aXNpb25CYWNrZmlsbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9taWdyYXRpb25zL3JlY29yZFJldmlzaW9uQmFja2ZpbGwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBeUdBLDBEQW9DQztBQTVJRCw4REFBNkY7QUFFaEYsUUFBQSx1Q0FBdUMsR0FDbEQsNEZBQTRGLENBQUM7QUFFbEYsUUFBQSxtQ0FBbUMsR0FBRyxHQUFHLENBQUM7QUFnQnZELDZFQUE2RTtBQUM3RSxNQUFNLGdCQUFnQixHQUFHLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDO0FBQzVDLE1BQU0sdUJBQXVCLEdBQUcsRUFBRSxjQUFjLEVBQUUsSUFBSSxFQUFFLENBQUM7QUFFekQsTUFBTSxPQUFPLEdBQXFEO0lBQ2hFLE1BQU0sRUFBRSxnQkFBZ0I7SUFDeEIsU0FBUyxFQUFFLEVBQUUsR0FBRyxFQUFFLENBQUMsZ0JBQWdCLEVBQUUsdUJBQXVCLENBQUMsRUFBRTtDQUNoRSxDQUFDO0FBRUYsTUFBTSxrQkFBa0IsR0FBd0IsSUFBSSxHQUFHLENBQUM7SUFDdEQsc0NBQXNDO0lBQ3RDLDZDQUE2QztDQUM5QyxDQUFDLENBQUM7QUFFSCxTQUFTLGVBQWUsQ0FBQyxLQUFjO0lBQ3JDLE1BQU0sT0FBTyxHQUFHLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUM1RCxPQUFPLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxpQ0FBaUMsQ0FBQztBQUN2RixDQUFDO0FBRUQsS0FBSyxVQUFVLGtCQUFrQixDQUMvQixVQUFnQyxFQUNoQyxJQUE0QixFQUM1QixTQUFpQjtJQUVqQixNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDOUIsSUFBSSxP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
@@ -1,6 +1,14 @@
1
1
  import 'reflect-metadata';
2
+ import { type DeletedRecordLifecycleOperation, type DeletedRecordLifecycleState } from '@researchdatabox/redbox-core';
2
3
  export declare class DeletedRecordClass {
3
4
  redboxOid?: string;
5
+ /** Sole authority for the current tombstone lifecycle revision. */
6
+ revision: number;
7
+ /** Assigned only by native lifecycle storage from the durable OID owner. */
8
+ incarnationId?: string;
9
+ brandId?: string;
10
+ lifecycleState: DeletedRecordLifecycleState;
11
+ lifecycleOperation?: DeletedRecordLifecycleOperation;
4
12
  deletedRecordMetadata?: Record<string, unknown>;
5
13
  dateDeleted: string;
6
14
  }
@@ -12,8 +12,40 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.DeletedRecordWLDef = exports.DeletedRecordClass = void 0;
13
13
  require("reflect-metadata");
14
14
  const redbox_core_1 = require("@researchdatabox/redbox-core");
15
+ /**
16
+ * Ordinary Waterline creates cannot choose a tombstone revision. The storage
17
+ * lifecycle path installs lineage-bearing tombstones through its native
18
+ * primitive after deriving the revision from authoritative active state.
19
+ */
20
+ const normalizeTombstoneLifecycle = (record, proceed) => {
21
+ record.revision = redbox_core_1.INITIAL_RECORD_REVISION;
22
+ delete record.incarnationId;
23
+ if (!(0, redbox_core_1.isDeletedRecordLifecycleState)(record.lifecycleState)) {
24
+ record.lifecycleState = 'deleted';
25
+ }
26
+ if (record.deletedRecordMetadata && typeof record.deletedRecordMetadata === 'object') {
27
+ delete record.deletedRecordMetadata.revision;
28
+ }
29
+ proceed();
30
+ };
31
+ /** Tombstone revisions only advance through the atomic tombstone primitives. */
32
+ const stripTombstoneRevision = (record, proceed) => {
33
+ delete record.revision;
34
+ delete record.incarnationId;
35
+ if (record.deletedRecordMetadata && typeof record.deletedRecordMetadata === 'object') {
36
+ delete record.deletedRecordMetadata.revision;
37
+ }
38
+ proceed();
39
+ };
15
40
  let DeletedRecordClass = class DeletedRecordClass {
16
41
  redboxOid;
42
+ /** Sole authority for the current tombstone lifecycle revision. */
43
+ revision = redbox_core_1.INITIAL_RECORD_REVISION;
44
+ /** Assigned only by native lifecycle storage from the durable OID owner. */
45
+ incarnationId;
46
+ brandId;
47
+ lifecycleState = 'deleted';
48
+ lifecycleOperation;
17
49
  deletedRecordMetadata;
18
50
  dateDeleted;
19
51
  };
@@ -22,6 +54,26 @@ __decorate([
22
54
  (0, redbox_core_1.Attr)({ type: 'string', unique: true }),
23
55
  __metadata("design:type", String)
24
56
  ], DeletedRecordClass.prototype, "redboxOid", void 0);
57
+ __decorate([
58
+ (0, redbox_core_1.Attr)({ type: 'number', defaultsTo: redbox_core_1.INITIAL_RECORD_REVISION, custom: redbox_core_1.isRecordRevision }),
59
+ __metadata("design:type", Number)
60
+ ], DeletedRecordClass.prototype, "revision", void 0);
61
+ __decorate([
62
+ (0, redbox_core_1.Attr)({ type: 'string', custom: redbox_core_1.isCanonicalSaveRequestId }),
63
+ __metadata("design:type", String)
64
+ ], DeletedRecordClass.prototype, "incarnationId", void 0);
65
+ __decorate([
66
+ (0, redbox_core_1.Attr)({ type: 'string' }),
67
+ __metadata("design:type", String)
68
+ ], DeletedRecordClass.prototype, "brandId", void 0);
69
+ __decorate([
70
+ (0, redbox_core_1.Attr)({ type: 'string', defaultsTo: 'deleted', isIn: redbox_core_1.DELETED_RECORD_LIFECYCLE_STATES }),
71
+ __metadata("design:type", String)
72
+ ], DeletedRecordClass.prototype, "lifecycleState", void 0);
73
+ __decorate([
74
+ (0, redbox_core_1.Attr)({ type: 'json', custom: redbox_core_1.isDeletedRecordLifecycleOperation }),
75
+ __metadata("design:type", Object)
76
+ ], DeletedRecordClass.prototype, "lifecycleOperation", void 0);
25
77
  __decorate([
26
78
  (0, redbox_core_1.Attr)({ type: 'json' }),
27
79
  __metadata("design:type", Object)
@@ -31,7 +83,9 @@ __decorate([
31
83
  __metadata("design:type", String)
32
84
  ], DeletedRecordClass.prototype, "dateDeleted", void 0);
33
85
  exports.DeletedRecordClass = DeletedRecordClass = __decorate([
86
+ (0, redbox_core_1.BeforeCreate)(normalizeTombstoneLifecycle),
87
+ (0, redbox_core_1.BeforeUpdate)(stripTombstoneRevision),
34
88
  (0, redbox_core_1.Entity)('deletedrecord', { datastore: 'redboxStorage' })
35
89
  ], DeletedRecordClass);
36
90
  exports.DeletedRecordWLDef = (0, redbox_core_1.toWaterlineModelDef)(DeletedRecordClass);
37
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRGVsZXRlZFJlY29yZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9tb2RlbHMvRGVsZXRlZFJlY29yZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7QUFBQSw0QkFBMEI7QUFDMUIsOERBQWlGO0FBRzFFLElBQU0sa0JBQWtCLEdBQXhCLE1BQU0sa0JBQWtCO0lBRXRCLFNBQVMsQ0FBVTtJQUduQixxQkFBcUIsQ0FBMkI7SUFHaEQsV0FBVyxDQUFVO0NBQzdCLENBQUE7QUFUWSxnREFBa0I7QUFFdEI7SUFETixJQUFBLGtCQUFJLEVBQUMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQzs7cURBQ2I7QUFHbkI7SUFETixJQUFBLGtCQUFJLEVBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUM7O2lFQUNnQztBQUdoRDtJQUROLElBQUEsa0JBQUksRUFBQyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsYUFBYSxFQUFFLElBQUksRUFBRSxDQUFDOzt1REFDbEI7NkJBUmpCLGtCQUFrQjtJQUQ5QixJQUFBLG9CQUFNLEVBQUMsZUFBZSxFQUFFLEVBQUUsU0FBUyxFQUFFLGVBQWUsRUFBRSxDQUFDO0dBQzNDLGtCQUFrQixDQVM5QjtBQUVZLFFBQUEsa0JBQWtCLEdBQUcsSUFBQSxpQ0FBbUIsRUFBQyxrQkFBa0IsQ0FBQyxDQUFDIn0=
91
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRGVsZXRlZFJlY29yZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9tb2RlbHMvRGVsZXRlZFJlY29yZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7QUFBQSw0QkFBMEI7QUFDMUIsOERBY3NDO0FBRXRDOzs7O0dBSUc7QUFDSCxNQUFNLDJCQUEyQixHQUFHLENBQUMsTUFBK0IsRUFBRSxPQUE4QixFQUFFLEVBQUU7SUFDdEcsTUFBTSxDQUFDLFFBQVEsR0FBRyxxQ0FBdUIsQ0FBQztJQUMxQyxPQUFPLE1BQU0sQ0FBQyxhQUFhLENBQUM7SUFDNUIsSUFBSSxDQUFDLElBQUEsMkNBQTZCLEVBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxFQUFFLENBQUM7UUFDMUQsTUFBTSxDQUFDLGNBQWMsR0FBRyxTQUFTLENBQUM7SUFDcEMsQ0FBQztJQUNELElBQUksTUFBTSxDQUFDLHFCQUFxQixJQUFJLE9BQU8sTUFBTSxDQUFDLHFCQUFxQixLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQ3JGLE9BQVEsTUFBTSxDQUFDLHFCQUFpRCxDQUFDLFFBQVEsQ0FBQztJQUM1RSxDQUFDO0lBQ0QsT0FBTyxFQUFFLENBQUM7QUFDWixDQUFDLENBQUM7QUFFRixnRkFBZ0Y7QUFDaEYsTUFBTSxzQkFBc0IsR0FBRyxDQUFDLE1BQStCLEVBQUUsT0FBOEIsRUFBRSxFQUFFO0lBQ2pHLE9BQU8sTUFBTSxDQUFDLFFBQVEsQ0FBQztJQUN2QixPQUFPLE1BQU0sQ0FBQyxhQUFhLENBQUM7SUFDNUIsSUFBSSxNQUFNLENBQUMscUJBQXFCLElBQUksT0FBTyxNQUFNLENBQUMscUJBQXFCLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDckYsT0FBUSxNQUFNLENBQUMscUJBQWlELENBQUMsUUFBUSxDQUFDO0lBQzVFLENBQUM7SUFDRCxPQUFPLEVBQUUsQ0FBQztBQUNaLENBQUMsQ0FBQztBQUtLLElBQU0sa0JBQWtCLEdBQXhCLE1BQU0sa0JBQWtCO0lBRXRCLFNBQVMsQ0FBVTtJQUUxQixtRUFBbUU7SUFFNUQsUUFBUSxHQUFXLHFDQUF1QixDQUFDO0lBRWxELDRFQUE0RTtJQUVyRSxhQUFhLENBQVU7SUFHdkIsT0FBTyxDQUFVO0lBR2pCLGNBQWMsR0FBZ0MsU0FBUyxDQUFDO0lBR3hELGtCQUFrQixDQUFtQztJQUdyRCxxQkFBcUIsQ0FBMkI7SUFHaEQsV0FBVyxDQUFVO0NBQzdCLENBQUE7QUExQlksZ0RBQWtCO0FBRXRCO0lBRE4sSUFBQSxrQkFBSSxFQUFDLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUM7O3FEQUNiO0FBSW5CO0lBRE4sSUFBQSxrQkFBSSxFQUFDLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUUscUNBQXVCLEVBQUUsTUFBTSxFQUFFLDhCQUFnQixFQUFFLENBQUM7O29EQUN0QztBQUkzQztJQUROLElBQUEsa0JBQUksRUFBQyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLHNDQUF3QixFQUFFLENBQUM7O3lEQUM3QjtBQUd2QjtJQUROLElBQUEsa0JBQUksRUFBQyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsQ0FBQzs7bURBQ0Q7QUFHakI7SUFETixJQUFBLGtCQUFJLEVBQUMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLDZDQUErQixFQUFFLENBQUM7OzBEQUN4QjtBQUd4RDtJQUROLElBQUEsa0JBQUksRUFBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLCtDQUFpQyxFQUFFLENBQUM7OzhEQUNOO0FBR3JEO0lBRE4sSUFBQSxrQkFBSSxFQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDOztpRUFDZ0M7QUFHaEQ7SUFETixJQUFBLGtCQUFJLEVBQUMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsQ0FBQzs7dURBQ2xCOzZCQXpCakIsa0JBQWtCO0lBSDlCLElBQUEsMEJBQVksRUFBQywyQkFBMkIsQ0FBQztJQUN6QyxJQUFBLDBCQUFZLEVBQUMsc0JBQXNCLENBQUM7SUFDcEMsSUFBQSxvQkFBTSxFQUFDLGVBQWUsRUFBRSxFQUFFLFNBQVMsRUFBRSxlQUFlLEVBQUUsQ0FBQztHQUMzQyxrQkFBa0IsQ0EwQjlCO0FBRVksUUFBQSxrQkFBa0IsR0FBRyxJQUFBLGlDQUFtQixFQUFDLGtCQUFrQixDQUFDLENBQUMifQ==
@@ -3,6 +3,11 @@ export type JsonMap = Record<string, unknown>;
3
3
  export declare class RecordClass {
4
4
  redboxOid?: string;
5
5
  harvestId?: string;
6
+ /** Server-owned. Clients must retain the opaque tag rather than assume 0. */
7
+ revision: number;
8
+ /** Assigned only by the native conditional-create storage boundary. */
9
+ incarnationId?: string;
10
+ lifecycleOperationId?: string;
6
11
  metaMetadata?: JsonMap;
7
12
  metadata?: JsonMap;
8
13
  workflow?: JsonMap;
@@ -12,9 +12,37 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.RecordWLDef = exports.RecordClass = void 0;
13
13
  require("reflect-metadata");
14
14
  const redbox_core_1 = require("@researchdatabox/redbox-core");
15
+ /**
16
+ * Ordinary Waterline creates always start a new record lineage. Lifecycle
17
+ * restoration uses a server-owned native storage path so it can continue a
18
+ * tombstone lineage without exposing a caller-controlled way to select the
19
+ * initial revision.
20
+ */
21
+ const normalizeServerRevision = (record, proceed) => {
22
+ record.revision = redbox_core_1.INITIAL_RECORD_REVISION;
23
+ delete record.incarnationId;
24
+ delete record.lifecycleOperationId;
25
+ proceed();
26
+ };
27
+ /**
28
+ * Only the atomic compare-and-set path may advance a revision, and it bypasses
29
+ * Waterline to do so. Any other update therefore leaves the stored revision
30
+ * untouched instead of writing a caller-supplied value.
31
+ */
32
+ const stripServerRevision = (record, proceed) => {
33
+ delete record.revision;
34
+ delete record.incarnationId;
35
+ delete record.lifecycleOperationId;
36
+ proceed();
37
+ };
15
38
  let RecordClass = class RecordClass {
16
39
  redboxOid;
17
40
  harvestId;
41
+ /** Server-owned. Clients must retain the opaque tag rather than assume 0. */
42
+ revision = redbox_core_1.INITIAL_RECORD_REVISION;
43
+ /** Assigned only by the native conditional-create storage boundary. */
44
+ incarnationId;
45
+ lifecycleOperationId;
18
46
  metaMetadata;
19
47
  metadata;
20
48
  workflow;
@@ -31,6 +59,18 @@ __decorate([
31
59
  (0, redbox_core_1.Attr)({ type: 'string' }),
32
60
  __metadata("design:type", String)
33
61
  ], RecordClass.prototype, "harvestId", void 0);
62
+ __decorate([
63
+ (0, redbox_core_1.Attr)({ type: 'number', defaultsTo: redbox_core_1.INITIAL_RECORD_REVISION, custom: redbox_core_1.isRecordRevision }),
64
+ __metadata("design:type", Number)
65
+ ], RecordClass.prototype, "revision", void 0);
66
+ __decorate([
67
+ (0, redbox_core_1.Attr)({ type: 'string', custom: redbox_core_1.isCanonicalSaveRequestId }),
68
+ __metadata("design:type", String)
69
+ ], RecordClass.prototype, "incarnationId", void 0);
70
+ __decorate([
71
+ (0, redbox_core_1.Attr)({ type: 'string', custom: redbox_core_1.isCanonicalSaveRequestId }),
72
+ __metadata("design:type", String)
73
+ ], RecordClass.prototype, "lifecycleOperationId", void 0);
34
74
  __decorate([
35
75
  (0, redbox_core_1.Attr)({ type: 'json' }),
36
76
  __metadata("design:type", Object)
@@ -56,9 +96,11 @@ __decorate([
56
96
  __metadata("design:type", String)
57
97
  ], RecordClass.prototype, "lastSaveDate", void 0);
58
98
  exports.RecordClass = RecordClass = __decorate([
99
+ (0, redbox_core_1.BeforeCreate)(normalizeServerRevision),
100
+ (0, redbox_core_1.BeforeUpdate)(stripServerRevision),
59
101
  (0, redbox_core_1.Entity)('record', {
60
102
  datastore: 'redboxStorage',
61
103
  })
62
104
  ], RecordClass);
63
105
  exports.RecordWLDef = (0, redbox_core_1.toWaterlineModelDef)(RecordClass);
64
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUmVjb3JkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21vZGVscy9SZWNvcmQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBQUEsNEJBQTBCO0FBQzFCLDhEQUFpRjtBQU8xRSxJQUFNLFdBQVcsR0FBakIsTUFBTSxXQUFXO0lBRWYsU0FBUyxDQUFVO0lBR25CLFNBQVMsQ0FBVTtJQUduQixZQUFZLENBQVc7SUFHdkIsUUFBUSxDQUFXO0lBR25CLFFBQVEsQ0FBVztJQUduQixhQUFhLENBQVc7SUFHeEIsV0FBVyxDQUFVO0lBR3JCLFlBQVksQ0FBVTtDQUM5QixDQUFBO0FBeEJZLGtDQUFXO0FBRWY7SUFETixJQUFBLGtCQUFJLEVBQUMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQzs7OENBQ2I7QUFHbkI7SUFETixJQUFBLGtCQUFJLEVBQUMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLENBQUM7OzhDQUNDO0FBR25CO0lBRE4sSUFBQSxrQkFBSSxFQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDOztpREFDTztBQUd2QjtJQUROLElBQUEsa0JBQUksRUFBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQzs7NkNBQ0c7QUFHbkI7SUFETixJQUFBLGtCQUFJLEVBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUM7OzZDQUNHO0FBR25CO0lBRE4sSUFBQSxrQkFBSSxFQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDOztrREFDUTtBQUd4QjtJQUROLElBQUEsa0JBQUksRUFBQyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsYUFBYSxFQUFFLElBQUksRUFBRSxDQUFDOztnREFDbEI7QUFHckI7SUFETixJQUFBLGtCQUFJLEVBQUMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsQ0FBQzs7aURBQ2pCO3NCQXZCbEIsV0FBVztJQUh2QixJQUFBLG9CQUFNLEVBQUMsUUFBUSxFQUFFO1FBQ2hCLFNBQVMsRUFBRSxlQUFlO0tBQzNCLENBQUM7R0FDVyxXQUFXLENBd0J2QjtBQUVZLFFBQUEsV0FBVyxHQUFHLElBQUEsaUNBQW1CLEVBQUMsV0FBVyxDQUFDLENBQUMifQ==
106
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUmVjb3JkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21vZGVscy9SZWNvcmQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBQUEsNEJBQTBCO0FBQzFCLDhEQVNzQztBQUl0Qzs7Ozs7R0FLRztBQUNILE1BQU0sdUJBQXVCLEdBQUcsQ0FBQyxNQUErQixFQUFFLE9BQThCLEVBQUUsRUFBRTtJQUNsRyxNQUFNLENBQUMsUUFBUSxHQUFHLHFDQUF1QixDQUFDO0lBQzFDLE9BQU8sTUFBTSxDQUFDLGFBQWEsQ0FBQztJQUM1QixPQUFPLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQztJQUNuQyxPQUFPLEVBQUUsQ0FBQztBQUNaLENBQUMsQ0FBQztBQUVGOzs7O0dBSUc7QUFDSCxNQUFNLG1CQUFtQixHQUFHLENBQUMsTUFBK0IsRUFBRSxPQUE4QixFQUFFLEVBQUU7SUFDOUYsT0FBTyxNQUFNLENBQUMsUUFBUSxDQUFDO0lBQ3ZCLE9BQU8sTUFBTSxDQUFDLGFBQWEsQ0FBQztJQUM1QixPQUFPLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQztJQUNuQyxPQUFPLEVBQUUsQ0FBQztBQUNaLENBQUMsQ0FBQztBQU9LLElBQU0sV0FBVyxHQUFqQixNQUFNLFdBQVc7SUFFZixTQUFTLENBQVU7SUFHbkIsU0FBUyxDQUFVO0lBRTFCLDZFQUE2RTtJQUV0RSxRQUFRLEdBQVcscUNBQXVCLENBQUM7SUFFbEQsdUVBQXVFO0lBRWhFLGFBQWEsQ0FBVTtJQUd2QixvQkFBb0IsQ0FBVTtJQUc5QixZQUFZLENBQVc7SUFHdkIsUUFBUSxDQUFXO0lBR25CLFFBQVEsQ0FBVztJQUduQixhQUFhLENBQVc7SUFHeEIsV0FBVyxDQUFVO0lBR3JCLFlBQVksQ0FBVTtDQUM5QixDQUFBO0FBbkNZLGtDQUFXO0FBRWY7SUFETixJQUFBLGtCQUFJLEVBQUMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQzs7OENBQ2I7QUFHbkI7SUFETixJQUFBLGtCQUFJLEVBQUMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLENBQUM7OzhDQUNDO0FBSW5CO0lBRE4sSUFBQSxrQkFBSSxFQUFDLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUUscUNBQXVCLEVBQUUsTUFBTSxFQUFFLDhCQUFnQixFQUFFLENBQUM7OzZDQUN0QztBQUkzQztJQUROLElBQUEsa0JBQUksRUFBQyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLHNDQUF3QixFQUFFLENBQUM7O2tEQUM3QjtBQUd2QjtJQUROLElBQUEsa0JBQUksRUFBQyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLHNDQUF3QixFQUFFLENBQUM7O3lEQUN0QjtBQUc5QjtJQUROLElBQUEsa0JBQUksRUFBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQzs7aURBQ087QUFHdkI7SUFETixJQUFBLGtCQUFJLEVBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUM7OzZDQUNHO0FBR25CO0lBRE4sSUFBQSxrQkFBSSxFQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDOzs2Q0FDRztBQUduQjtJQUROLElBQUEsa0JBQUksRUFBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQzs7a0RBQ1E7QUFHeEI7SUFETixJQUFBLGtCQUFJLEVBQUMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsQ0FBQzs7Z0RBQ2xCO0FBR3JCO0lBRE4sSUFBQSxrQkFBSSxFQUFDLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxhQUFhLEVBQUUsSUFBSSxFQUFFLENBQUM7O2lEQUNqQjtzQkFsQ2xCLFdBQVc7SUFMdkIsSUFBQSwwQkFBWSxFQUFDLHVCQUF1QixDQUFDO0lBQ3JDLElBQUEsMEJBQVksRUFBQyxtQkFBbUIsQ0FBQztJQUNqQyxJQUFBLG9CQUFNLEVBQUMsUUFBUSxFQUFFO1FBQ2hCLFNBQVMsRUFBRSxlQUFlO0tBQzNCLENBQUM7R0FDVyxXQUFXLENBbUN2QjtBQUVZLFFBQUEsV0FBVyxHQUFHLElBQUEsaUNBQW1CLEVBQUMsV0FBVyxDQUFDLENBQUMifQ==
@@ -5,5 +5,7 @@ export declare class RecordAuditClass {
5
5
  record?: Record<string, unknown>;
6
6
  dateCreated: string;
7
7
  action?: string;
8
+ executionSummary?: Record<string, unknown>;
9
+ concurrency?: Record<string, unknown>;
8
10
  }
9
11
  export declare const RecordAuditWLDef: import("@researchdatabox/redbox-core").WaterlineModelDefinition;
@@ -18,6 +18,8 @@ let RecordAuditClass = class RecordAuditClass {
18
18
  record;
19
19
  dateCreated;
20
20
  action;
21
+ executionSummary;
22
+ concurrency;
21
23
  };
22
24
  exports.RecordAuditClass = RecordAuditClass;
23
25
  __decorate([
@@ -40,8 +42,16 @@ __decorate([
40
42
  (0, redbox_core_1.Attr)({ type: 'string' }),
41
43
  __metadata("design:type", String)
42
44
  ], RecordAuditClass.prototype, "action", void 0);
45
+ __decorate([
46
+ (0, redbox_core_1.Attr)({ type: 'json' }),
47
+ __metadata("design:type", Object)
48
+ ], RecordAuditClass.prototype, "executionSummary", void 0);
49
+ __decorate([
50
+ (0, redbox_core_1.Attr)({ type: 'json' }),
51
+ __metadata("design:type", Object)
52
+ ], RecordAuditClass.prototype, "concurrency", void 0);
43
53
  exports.RecordAuditClass = RecordAuditClass = __decorate([
44
54
  (0, redbox_core_1.Entity)('recordaudit', { datastore: 'redboxStorage' })
45
55
  ], RecordAuditClass);
46
56
  exports.RecordAuditWLDef = (0, redbox_core_1.toWaterlineModelDef)(RecordAuditClass);
47
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUmVjb3JkQXVkaXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbW9kZWxzL1JlY29yZEF1ZGl0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztBQUFBLDRCQUEwQjtBQUMxQiw4REFBaUY7QUFHMUUsSUFBTSxnQkFBZ0IsR0FBdEIsTUFBTSxnQkFBZ0I7SUFFcEIsU0FBUyxDQUFVO0lBR25CLElBQUksQ0FBMkI7SUFHL0IsTUFBTSxDQUEyQjtJQUdqQyxXQUFXLENBQVU7SUFHckIsTUFBTSxDQUFVO0NBQ3hCLENBQUE7QUFmWSw0Q0FBZ0I7QUFFcEI7SUFETixJQUFBLGtCQUFJLEVBQUMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLENBQUM7O21EQUNDO0FBR25CO0lBRE4sSUFBQSxrQkFBSSxFQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDOzs4Q0FDZTtBQUcvQjtJQUROLElBQUEsa0JBQUksRUFBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQzs7Z0RBQ2lCO0FBR2pDO0lBRE4sSUFBQSxrQkFBSSxFQUFDLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxhQUFhLEVBQUUsSUFBSSxFQUFFLENBQUM7O3FEQUNsQjtBQUdyQjtJQUROLElBQUEsa0JBQUksRUFBQyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsQ0FBQzs7Z0RBQ0Y7MkJBZFosZ0JBQWdCO0lBRDVCLElBQUEsb0JBQU0sRUFBQyxhQUFhLEVBQUUsRUFBRSxTQUFTLEVBQUUsZUFBZSxFQUFFLENBQUM7R0FDekMsZ0JBQWdCLENBZTVCO0FBRVksUUFBQSxnQkFBZ0IsR0FBRyxJQUFBLGlDQUFtQixFQUFDLGdCQUFnQixDQUFDLENBQUMifQ==
57
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUmVjb3JkQXVkaXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbW9kZWxzL1JlY29yZEF1ZGl0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztBQUFBLDRCQUEwQjtBQUMxQiw4REFBaUY7QUFHMUUsSUFBTSxnQkFBZ0IsR0FBdEIsTUFBTSxnQkFBZ0I7SUFFcEIsU0FBUyxDQUFVO0lBR25CLElBQUksQ0FBMkI7SUFHL0IsTUFBTSxDQUEyQjtJQUdqQyxXQUFXLENBQVU7SUFHckIsTUFBTSxDQUFVO0lBR2hCLGdCQUFnQixDQUEyQjtJQUczQyxXQUFXLENBQTJCO0NBQzlDLENBQUE7QUFyQlksNENBQWdCO0FBRXBCO0lBRE4sSUFBQSxrQkFBSSxFQUFDLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxDQUFDOzttREFDQztBQUduQjtJQUROLElBQUEsa0JBQUksRUFBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQzs7OENBQ2U7QUFHL0I7SUFETixJQUFBLGtCQUFJLEVBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUM7O2dEQUNpQjtBQUdqQztJQUROLElBQUEsa0JBQUksRUFBQyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsYUFBYSxFQUFFLElBQUksRUFBRSxDQUFDOztxREFDbEI7QUFHckI7SUFETixJQUFBLGtCQUFJLEVBQUMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLENBQUM7O2dEQUNGO0FBR2hCO0lBRE4sSUFBQSxrQkFBSSxFQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDOzswREFDMkI7QUFHM0M7SUFETixJQUFBLGtCQUFJLEVBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUM7O3FEQUNzQjsyQkFwQmxDLGdCQUFnQjtJQUQ1QixJQUFBLG9CQUFNLEVBQUMsYUFBYSxFQUFFLEVBQUUsU0FBUyxFQUFFLGVBQWUsRUFBRSxDQUFDO0dBQ3pDLGdCQUFnQixDQXFCNUI7QUFFWSxRQUFBLGdCQUFnQixHQUFHLElBQUEsaUNBQW1CLEVBQUMsZ0JBQWdCLENBQUMsQ0FBQyJ9