@chaos-overlords/bug-reports 0.1.0 → 0.3.0

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/blobs.d.ts CHANGED
@@ -2,6 +2,17 @@ import type { R2Bucket } from '@cloudflare/workers-types';
2
2
  import type { BlobStore } from './ports';
3
3
  /** What an archive is stored as, wherever it lands. */
4
4
  export declare const ARCHIVE_CONTENT_TYPE = "application/octet-stream";
5
+ /**
6
+ * The prefix an archive the client did not scrub is filed under.
7
+ *
8
+ * `anonymized` is whatever the client said, and the client is the one piece of this path nobody
9
+ * operates. A journal that was not scrubbed carries other players' names and their Comlink text, so
10
+ * it is kept apart rather than turned away: the report is still worth having, and the person
11
+ * triaging it is entitled to know what they are about to open before they open it. Triage tooling
12
+ * filters on the prefix; nothing else treats the two differently.
13
+ */
14
+ export declare const UNSCRUBBED_ARCHIVE_PREFIX = "bug-reports-unscrubbed";
15
+ export declare const ARCHIVE_PREFIX = "bug-reports";
5
16
  /**
6
17
  * The key an archive is filed under.
7
18
  *
@@ -9,7 +20,7 @@ export declare const ARCHIVE_CONTENT_TYPE = "application/octet-stream";
9
20
  * with the report id, which is already a random UUID — nothing in the key is derived from the
10
21
  * report's contents, so a key cannot leak one.
11
22
  */
12
- export declare function archiveKey(id: string, receivedAt: Date): string;
23
+ export declare function archiveKey(id: string, receivedAt: Date, anonymized?: boolean): string;
13
24
  /** Cloudflare R2, which is where a public deployment puts the archives. */
14
25
  export declare function createR2BlobStore(bucket: R2Bucket): BlobStore;
15
26
  /** An in-process store, for tests and for a `sqlite::memory:` development server. */
@@ -1 +1 @@
1
- {"version":3,"file":"blobs.d.ts","sourceRoot":"","sources":["../src/blobs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAExC,uDAAuD;AACvD,eAAO,MAAM,oBAAoB,6BAA6B,CAAA;AAE9D;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,GAAG,MAAM,CAG/D;AAED,2EAA2E;AAC3E,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,QAAQ,GAAG,SAAS,CAc7D;AAED,qFAAqF;AACrF,wBAAgB,qBAAqB,IAAI,SAAS,CAajD"}
1
+ {"version":3,"file":"blobs.d.ts","sourceRoot":"","sources":["../src/blobs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAExC,uDAAuD;AACvD,eAAO,MAAM,oBAAoB,6BAA6B,CAAA;AAE9D;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,2BAA2B,CAAA;AAEjE,eAAO,MAAM,cAAc,gBAAgB,CAAA;AAE3C;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,UAAO,GAAG,MAAM,CAIlF;AAED,2EAA2E;AAC3E,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,QAAQ,GAAG,SAAS,CAc7D;AAED,qFAAqF;AACrF,wBAAgB,qBAAqB,IAAI,SAAS,CAajD"}
package/dist/blobs.js CHANGED
@@ -1,5 +1,16 @@
1
1
  /** What an archive is stored as, wherever it lands. */
2
2
  export const ARCHIVE_CONTENT_TYPE = 'application/octet-stream';
3
+ /**
4
+ * The prefix an archive the client did not scrub is filed under.
5
+ *
6
+ * `anonymized` is whatever the client said, and the client is the one piece of this path nobody
7
+ * operates. A journal that was not scrubbed carries other players' names and their Comlink text, so
8
+ * it is kept apart rather than turned away: the report is still worth having, and the person
9
+ * triaging it is entitled to know what they are about to open before they open it. Triage tooling
10
+ * filters on the prefix; nothing else treats the two differently.
11
+ */
12
+ export const UNSCRUBBED_ARCHIVE_PREFIX = 'bug-reports-unscrubbed';
13
+ export const ARCHIVE_PREFIX = 'bug-reports';
3
14
  /**
4
15
  * The key an archive is filed under.
5
16
  *
@@ -7,9 +18,10 @@ export const ARCHIVE_CONTENT_TYPE = 'application/octet-stream';
7
18
  * with the report id, which is already a random UUID — nothing in the key is derived from the
8
19
  * report's contents, so a key cannot leak one.
9
20
  */
10
- export function archiveKey(id, receivedAt) {
21
+ export function archiveKey(id, receivedAt, anonymized = true) {
11
22
  const day = receivedAt.toISOString().slice(0, 10);
12
- return `bug-reports/${day}/${id}.rchjournal`;
23
+ const prefix = anonymized ? ARCHIVE_PREFIX : UNSCRUBBED_ARCHIVE_PREFIX;
24
+ return `${prefix}/${day}/${id}.rchjournal`;
13
25
  }
14
26
  /** Cloudflare R2, which is where a public deployment puts the archives. */
15
27
  export function createR2BlobStore(bucket) {
package/dist/blobs.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"blobs.js","sourceRoot":"","sources":["../src/blobs.ts"],"names":[],"mappings":"AAGA,uDAAuD;AACvD,MAAM,CAAC,MAAM,oBAAoB,GAAG,0BAA0B,CAAA;AAE9D;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,EAAU,EAAE,UAAgB;IACrD,MAAM,GAAG,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACjD,OAAO,eAAe,GAAG,IAAI,EAAE,aAAa,CAAA;AAC9C,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,iBAAiB,CAAC,MAAgB;IAChD,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,WAAW;YAC/B,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,YAAY,EAAE,EAAE,WAAW,EAAE,EAAE,CAAC,CAAA;QACjE,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,GAAG;YACX,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YACpC,IAAI,CAAC,MAAM;gBAAE,OAAO,IAAI,CAAA;YACxB,OAAO,IAAI,UAAU,CAAC,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC,CAAA;QACnD,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,GAAG;YACd,MAAM,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAC1B,CAAC;KACF,CAAA;AACH,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,qBAAqB;IACnC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAsB,CAAA;IAC7C,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK;YAClB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAA;QACjC,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,GAAG;YACX,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAA;QACjC,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,GAAG;YACd,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QACrB,CAAC;KACF,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"blobs.js","sourceRoot":"","sources":["../src/blobs.ts"],"names":[],"mappings":"AAGA,uDAAuD;AACvD,MAAM,CAAC,MAAM,oBAAoB,GAAG,0BAA0B,CAAA;AAE9D;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,wBAAwB,CAAA;AAEjE,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAA;AAE3C;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,EAAU,EAAE,UAAgB,EAAE,UAAU,GAAG,IAAI;IACxE,MAAM,GAAG,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACjD,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,yBAAyB,CAAA;IACtE,OAAO,GAAG,MAAM,IAAI,GAAG,IAAI,EAAE,aAAa,CAAA;AAC5C,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,iBAAiB,CAAC,MAAgB;IAChD,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,WAAW;YAC/B,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,YAAY,EAAE,EAAE,WAAW,EAAE,EAAE,CAAC,CAAA;QACjE,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,GAAG;YACX,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YACpC,IAAI,CAAC,MAAM;gBAAE,OAAO,IAAI,CAAA;YACxB,OAAO,IAAI,UAAU,CAAC,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC,CAAA;QACnD,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,GAAG;YACd,MAAM,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAC1B,CAAC;KACF,CAAA;AACH,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,qBAAqB;IACnC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAsB,CAAA;IAC7C,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK;YAClB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAA;QACjC,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,GAAG;YACX,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAA;QACjC,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,GAAG;YACd,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QACrB,CAAC;KACF,CAAA;AACH,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export { ARCHIVE_CONTENT_TYPE, archiveKey, createMemoryBlobStore, createR2BlobStore, } from './blobs';
1
+ export { ARCHIVE_CONTENT_TYPE, ARCHIVE_PREFIX, archiveKey, createMemoryBlobStore, createR2BlobStore, UNSCRUBBED_ARCHIVE_PREFIX, } from './blobs';
2
2
  export type { BlobStore, BugReportRepository, StoredBugReport, StoredBugReportState, } from './ports';
3
3
  export { type BugReportDatabase, createBugReportRepository } from './repository';
4
4
  export * as bugReportSchema from './schema';
5
- export { type BugReportService, type BugReportServiceDeps, createBugReportService, decodeBase64, } from './service';
5
+ export { type BugReportRetention, type BugReportService, type BugReportServiceDeps, createBugReportService, DEFAULT_BUG_REPORT_RETENTION, decodeBase64, } from './service';
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,UAAU,EACV,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,SAAS,CAAA;AAChB,YAAY,EACV,SAAS,EACT,mBAAmB,EACnB,eAAe,EACf,oBAAoB,GACrB,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,KAAK,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AAChF,OAAO,KAAK,eAAe,MAAM,UAAU,CAAA;AAC3C,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,sBAAsB,EACtB,YAAY,GACb,MAAM,WAAW,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,UAAU,EACV,qBAAqB,EACrB,iBAAiB,EACjB,yBAAyB,GAC1B,MAAM,SAAS,CAAA;AAChB,YAAY,EACV,SAAS,EACT,mBAAmB,EACnB,eAAe,EACf,oBAAoB,GACrB,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,KAAK,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AAChF,OAAO,KAAK,eAAe,MAAM,UAAU,CAAA;AAC3C,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,sBAAsB,EACtB,4BAA4B,EAC5B,YAAY,GACb,MAAM,WAAW,CAAA"}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- export { ARCHIVE_CONTENT_TYPE, archiveKey, createMemoryBlobStore, createR2BlobStore, } from './blobs';
1
+ export { ARCHIVE_CONTENT_TYPE, ARCHIVE_PREFIX, archiveKey, createMemoryBlobStore, createR2BlobStore, UNSCRUBBED_ARCHIVE_PREFIX, } from './blobs';
2
2
  export { createBugReportRepository } from './repository';
3
3
  export * as bugReportSchema from './schema';
4
- export { createBugReportService, decodeBase64, } from './service';
4
+ export { createBugReportService, DEFAULT_BUG_REPORT_RETENTION, decodeBase64, } from './service';
5
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,UAAU,EACV,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,SAAS,CAAA;AAOhB,OAAO,EAA0B,yBAAyB,EAAE,MAAM,cAAc,CAAA;AAChF,OAAO,KAAK,eAAe,MAAM,UAAU,CAAA;AAC3C,OAAO,EAGL,sBAAsB,EACtB,YAAY,GACb,MAAM,WAAW,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,UAAU,EACV,qBAAqB,EACrB,iBAAiB,EACjB,yBAAyB,GAC1B,MAAM,SAAS,CAAA;AAOhB,OAAO,EAA0B,yBAAyB,EAAE,MAAM,cAAc,CAAA;AAChF,OAAO,KAAK,eAAe,MAAM,UAAU,CAAA;AAC3C,OAAO,EAIL,sBAAsB,EACtB,4BAA4B,EAC5B,YAAY,GACb,MAAM,WAAW,CAAA"}
package/dist/ports.d.ts CHANGED
@@ -22,12 +22,20 @@ export interface StoredBugReportState {
22
22
  /** The base64 archive when it was small enough to keep in the row, or null. */
23
23
  body: string | null;
24
24
  }
25
- /** The one write and the two reads this area needs; implemented over Drizzle, faked in tests. */
25
+ /** The writes and reads this area needs; implemented over Drizzle, faked in tests. */
26
26
  export interface BugReportRepository {
27
27
  insert(report: StoredBugReport): Promise<void>;
28
28
  get(id: string): Promise<StoredBugReport | null>;
29
29
  /** Newest first, for triage. */
30
30
  list(limit: number): Promise<StoredBugReport[]>;
31
+ /** Compressed bytes filed since `since`, which is what the daily byte budget is spent against. */
32
+ bytesSince(since: Date): Promise<number>;
33
+ /**
34
+ * Delete reports received before `before`, oldest first, at most `limit` of them. Returns the
35
+ * blob keys of the ones that went, so the caller can drop the objects the rows pointed at — the
36
+ * blob store is a different system and nothing cascades into it.
37
+ */
38
+ deleteBefore(before: Date, limit: number): Promise<string[]>;
31
39
  }
32
40
  /**
33
41
  * Somewhere to put bytes that have no business being in a database row.
@@ -1 +1 @@
1
- {"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../src/ports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAA;AAExF,kFAAkF;AAClF,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,UAAU,EAAE,IAAI,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,MAAM,CAAA;IACrB,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,sBAAsB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAA;IACjD,KAAK,EAAE,oBAAoB,GAAG,IAAI,CAAA;CACnC;AAED,sDAAsD;AACtD,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,cAAc,CAAA;IACrB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,iBAAiB,EAAE,MAAM,CAAA;IACzB,eAAe,EAAE,MAAM,CAAA;IACvB,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,OAAO,CAAA;IACnB,2FAA2F;IAC3F,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,+EAA+E;IAC/E,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CACpB;AAED,iGAAiG;AACjG,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9C,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAA;IAChD,gCAAgC;IAChC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAA;CAChD;AAED;;;;;;GAMG;AACH,MAAM,WAAW,SAAS;IACxB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACvE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAA;IAC5C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACnC"}
1
+ {"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../src/ports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAA;AAExF,kFAAkF;AAClF,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,UAAU,EAAE,IAAI,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,MAAM,CAAA;IACrB,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,sBAAsB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAA;IACjD,KAAK,EAAE,oBAAoB,GAAG,IAAI,CAAA;CACnC;AAED,sDAAsD;AACtD,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,cAAc,CAAA;IACrB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,iBAAiB,EAAE,MAAM,CAAA;IACzB,eAAe,EAAE,MAAM,CAAA;IACvB,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,OAAO,CAAA;IACnB,2FAA2F;IAC3F,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,+EAA+E;IAC/E,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CACpB;AAED,sFAAsF;AACtF,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9C,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAA;IAChD,gCAAgC;IAChC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAA;IAC/C,kGAAkG;IAClG,UAAU,CAAC,KAAK,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACxC;;;;OAIG;IACH,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;CAC7D;AAED;;;;;;GAMG;AACH,MAAM,WAAW,SAAS;IACxB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACvE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAA;IAC5C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACnC"}
@@ -1 +1 @@
1
- {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../src/repository.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAmB,MAAM,SAAS,CAAA;AACnE,OAAO,KAAK,KAAK,MAAM,MAAM,UAAU,CAAA;AAGvC;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,kBAAkB,CAAC,MAAM,GAAG,OAAO,EAAE,OAAO,EAAE,OAAO,MAAM,CAAC,CAAA;AAI5F,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,iBAAiB,GAAG,mBAAmB,CAqBpF"}
1
+ {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../src/repository.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAmB,MAAM,SAAS,CAAA;AACnE,OAAO,KAAK,KAAK,MAAM,MAAM,UAAU,CAAA;AAGvC;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,kBAAkB,CAAC,MAAM,GAAG,OAAO,EAAE,OAAO,EAAE,OAAO,MAAM,CAAC,CAAA;AAI5F,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,iBAAiB,GAAG,mBAAmB,CA8CpF"}
@@ -1,4 +1,4 @@
1
- import { desc, eq } from 'drizzle-orm';
1
+ import { asc, desc, eq, gte, inArray, lt, sql } from 'drizzle-orm';
2
2
  import { bugReports } from './schema';
3
3
  export function createBugReportRepository(db) {
4
4
  return {
@@ -18,6 +18,25 @@ export function createBugReportRepository(db) {
18
18
  .limit(limit);
19
19
  return rows.map(fromRow);
20
20
  },
21
+ async bytesSince(since) {
22
+ const rows = await db
23
+ .select({ bytes: sql `coalesce(sum(${bugReports.stateCompressedBytes}), 0)` })
24
+ .from(bugReports)
25
+ .where(gte(bugReports.receivedAt, since));
26
+ return Number(rows[0]?.bytes ?? 0);
27
+ },
28
+ async deleteBefore(before, limit) {
29
+ const doomed = await db
30
+ .select({ id: bugReports.id, blobKey: bugReports.blobKey })
31
+ .from(bugReports)
32
+ .where(lt(bugReports.receivedAt, before))
33
+ .orderBy(asc(bugReports.receivedAt))
34
+ .limit(limit);
35
+ if (doomed.length === 0)
36
+ return [];
37
+ await db.delete(bugReports).where(inArray(bugReports.id, doomed.map((row) => row.id)));
38
+ return doomed.flatMap((row) => (row.blobKey === null ? [] : [row.blobKey]));
39
+ },
21
40
  };
22
41
  }
23
42
  function toRow(report) {
@@ -1 +1 @@
1
- {"version":3,"file":"repository.js","sourceRoot":"","sources":["../src/repository.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"repository.js","sourceRoot":"","sources":["../src/repository.ts"],"names":[],"mappings":"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"}
package/dist/service.d.ts CHANGED
@@ -1,6 +1,29 @@
1
1
  import { type BugReportReceipt, type SubmitBugReportRequest } from '@chaos-overlords/contracts';
2
2
  import { type Clock, type Logger } from '@chaos-overlords/kernel';
3
3
  import type { BlobStore, BugReportRepository, StoredBugReport } from './ports';
4
+ /**
5
+ * What an intake may accumulate.
6
+ *
7
+ * The per-address, per-minute limiter in front of the route stops one client in a retry loop. It
8
+ * does nothing about the other shape: reports arriving from many addresses, a few a minute each,
9
+ * for as long as anybody cares to keep sending them. Nothing in the intake path ever deleted
10
+ * anything, so that was unbounded object storage and unbounded rows on the central deployment.
11
+ *
12
+ * Two bounds and a sweep. The byte budget is a whole-day ceiling on attached journals across every
13
+ * reporter, which is what stops a distributed flood without turning away the one player who files
14
+ * three reports in an afternoon: over budget, the report is still accepted and the journal is
15
+ * dropped, because the description is the part worth having. Retention then deletes the rows and
16
+ * the objects once they are older than the window.
17
+ */
18
+ export interface BugReportRetention {
19
+ /** Attached journal bytes accepted per rolling day across all reporters. 0 means no ceiling. */
20
+ dailyStateBytes: number;
21
+ /** Age after which a report and its archive are deleted. 0 keeps everything. */
22
+ maxAgeMs: number;
23
+ /** Reports deleted per sweep, so one pass cannot monopolise the database. */
24
+ batchSize: number;
25
+ }
26
+ export declare const DEFAULT_BUG_REPORT_RETENTION: BugReportRetention;
4
27
  export interface BugReportServiceDeps {
5
28
  repository: BugReportRepository;
6
29
  clock: Clock;
@@ -10,6 +33,8 @@ export interface BugReportServiceDeps {
10
33
  * large ones away — see {@link BugReportService.submit}.
11
34
  */
12
35
  blobs?: BlobStore;
36
+ /** Overrides {@link DEFAULT_BUG_REPORT_RETENTION}; a runtime maps its configuration onto it. */
37
+ retention?: BugReportRetention;
13
38
  }
14
39
  export interface BugReportService {
15
40
  submit(request: SubmitBugReportRequest): Promise<BugReportReceipt>;
@@ -18,6 +43,8 @@ export interface BugReportService {
18
43
  list(limit: number): Promise<StoredBugReport[]>;
19
44
  /** The archive itself, wherever it was kept. */
20
45
  archive(id: string): Promise<Uint8Array | null>;
46
+ /** Deletes reports past the retention window with their archives; returns how many went. */
47
+ collect(): Promise<number>;
21
48
  }
22
49
  /**
23
50
  * Intake for one bug report.
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC5B,MAAM,4BAA4B,CAAA;AACnC,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,MAAM,EAA8B,MAAM,yBAAyB,CAAA;AAE7F,OAAO,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAE9E,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,mBAAmB,CAAA;IAC/B,KAAK,EAAE,KAAK,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAClE,gGAAgG;IAChG,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAA;IAChD,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAA;IAC/C,gDAAgD;IAChD,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAA;CAChD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,gBAAgB,CAqHnF;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAKtD"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC5B,MAAM,4BAA4B,CAAA;AACnC,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,MAAM,EAA8B,MAAM,yBAAyB,CAAA;AAE7F,OAAO,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAE9E;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,kBAAkB;IACjC,gGAAgG;IAChG,eAAe,EAAE,MAAM,CAAA;IACvB,gFAAgF;IAChF,QAAQ,EAAE,MAAM,CAAA;IAChB,6EAA6E;IAC7E,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,eAAO,MAAM,4BAA4B,EAAE,kBAI1C,CAAA;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,mBAAmB,CAAA;IAC/B,KAAK,EAAE,KAAK,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,gGAAgG;IAChG,SAAS,CAAC,EAAE,kBAAkB,CAAA;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAClE,gGAAgG;IAChG,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAA;IAChD,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAA;IAC/C,gDAAgD;IAChD,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAA;IAC/C,4FAA4F;IAC5F,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;CAC3B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,gBAAgB,CA4KnF;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAKtD"}
package/dist/service.js CHANGED
@@ -1,6 +1,11 @@
1
1
  import { BUG_REPORT_LIMITS, } from '@chaos-overlords/contracts';
2
2
  import { sha256Hex, ValidationError } from '@chaos-overlords/kernel';
3
3
  import { ARCHIVE_CONTENT_TYPE, archiveKey } from './blobs';
4
+ export const DEFAULT_BUG_REPORT_RETENTION = {
5
+ dailyStateBytes: 512 * 1024 * 1024,
6
+ maxAgeMs: 90 * 24 * 60 * 60 * 1000,
7
+ batchSize: 100,
8
+ };
4
9
  /**
5
10
  * Intake for one bug report.
6
11
  *
@@ -22,13 +27,12 @@ import { ARCHIVE_CONTENT_TYPE, archiveKey } from './blobs';
22
27
  */
23
28
  export function createBugReportService(deps) {
24
29
  const { repository, clock, logger, blobs } = deps;
30
+ const retention = deps.retention ?? DEFAULT_BUG_REPORT_RETENTION;
25
31
  return {
26
32
  async submit(request) {
27
33
  const receivedAt = clock.now();
28
34
  const id = crypto.randomUUID();
29
- const stored = request.state
30
- ? await placeArchive(id, receivedAt, request.state)
31
- : { state: null, outcome: 'not_sent' };
35
+ const stored = await file(id, receivedAt, request.state);
32
36
  const report = {
33
37
  id,
34
38
  receivedAt,
@@ -62,6 +66,24 @@ export function createBugReportService(deps) {
62
66
  },
63
67
  get: (id) => repository.get(id),
64
68
  list: (limit) => repository.list(limit),
69
+ async collect() {
70
+ if (retention.maxAgeMs <= 0)
71
+ return 0;
72
+ const before = new Date(clock.now().getTime() - retention.maxAgeMs);
73
+ const keys = await repository.deleteBefore(before, retention.batchSize);
74
+ // The rows are already gone, so an object that cannot be removed is an orphan to sweep later
75
+ // rather than a report that came back. Deleting the row first is the right order: the other
76
+ // way round leaves a row pointing at an object that is not there.
77
+ for (const key of keys)
78
+ await forget(key);
79
+ if (keys.length > 0) {
80
+ logger.info('bug report retention deleted reports', {
81
+ deleted: keys.length,
82
+ before: before.toISOString(),
83
+ });
84
+ }
85
+ return keys.length;
86
+ },
65
87
  async archive(id) {
66
88
  const report = await repository.get(id);
67
89
  const state = report?.state;
@@ -80,6 +102,40 @@ export function createBugReportService(deps) {
80
102
  * hash to what its own report claims is worse than no archive, because somebody would spend an
81
103
  * afternoon replaying it before finding out.
82
104
  */
105
+ /**
106
+ * Where the attached journal came to rest, if it came with one and the day had room for it.
107
+ */
108
+ async function file(id, receivedAt, state) {
109
+ if (!state)
110
+ return { state: null, outcome: 'not_sent' };
111
+ if (!(await withinDailyBudget(receivedAt, state)))
112
+ return { state: null, outcome: 'omitted' };
113
+ return placeArchive(id, receivedAt, state);
114
+ }
115
+ /**
116
+ * Whether the day still has room for this archive.
117
+ *
118
+ * Measured against what is already filed rather than against a counter, so it survives a restart
119
+ * and is shared by every isolate of a Worker deployment. A report that does not fit keeps its
120
+ * description and loses its journal, and the receipt says `omitted` so the player knows.
121
+ */
122
+ async function withinDailyBudget(receivedAt, state) {
123
+ if (retention.dailyStateBytes <= 0)
124
+ return true;
125
+ const since = new Date(receivedAt.getTime() - 24 * 60 * 60 * 1000);
126
+ const spent = await repository.bytesSince(since);
127
+ // The declared encoded length is what is checked, before anything is decoded: deciding after the
128
+ // decode would mean the budget is only applied to bytes already in memory.
129
+ const incoming = Math.ceil((state.body.length * 3) / 4);
130
+ if (spent + incoming <= retention.dailyStateBytes)
131
+ return true;
132
+ logger.warn('bug report state dropped: the daily archive budget is spent', {
133
+ spent,
134
+ incoming,
135
+ budget: retention.dailyStateBytes,
136
+ });
137
+ return false;
138
+ }
83
139
  async function placeArchive(id, receivedAt, state) {
84
140
  const bytes = decodeBase64(state.body);
85
141
  const digest = await sha256Hex(bytes);
@@ -97,7 +153,7 @@ export function createBugReportService(deps) {
97
153
  anonymized: state.anonymized,
98
154
  };
99
155
  if (blobs) {
100
- const key = archiveKey(id, receivedAt);
156
+ const key = archiveKey(id, receivedAt, state.anonymized);
101
157
  await blobs.put(key, bytes, ARCHIVE_CONTENT_TYPE);
102
158
  return { state: { ...common, blobKey: key, body: null }, outcome: 'stored' };
103
159
  }
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chaos-overlords/bug-reports",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Bug report intake: its own Drizzle schema, migration lineage and database, plus the blob store the compressed match journals are kept in. Deliberately shares nothing with the multiplayer storage.",
5
5
  "keywords": [
6
6
  "chaos-overlords",
@@ -54,8 +54,8 @@
54
54
  "provenance": true
55
55
  },
56
56
  "dependencies": {
57
- "@chaos-overlords/contracts": "0.1.0",
58
- "@chaos-overlords/kernel": "0.1.0",
57
+ "@chaos-overlords/contracts": "0.3.0",
58
+ "@chaos-overlords/kernel": "0.3.0",
59
59
  "drizzle-orm": "^0.45.2"
60
60
  },
61
61
  "devDependencies": {