Repository navigation
chore: land the cleanup campaign on main - #87
Merged
Merged
Conversation
* refactor: look up the index groups, container keys, floating values and schemas by own key * refactor: read class prototypes through a checked helper * refactor(modifiers): give the event handler alias no type parameter * refactor(encryption): check that the auth-tag methods are callable * refactor(table): collect the mixins without reading any * refactor(database): insert the fixture rows without an any local * test: read the stored rows, the module exports and the sort keys without any * chore: lower the ratchet ceilings * refactor(modifiers): type the receiver of the generated accessors * chore: lower the no-unsafe-return ceiling * refactor(records): look up the unlock arguments and the floating values by own key * chore: lower the no-inherited-key-lookup ceiling * refactor(table): assert the mixin subclass to the declared return type * refactor(modifiers): restore the container unlock lookup to its base form
…the package (#55) * test(metadata): pin the metadata stored by an older copy of the package * fix(metadata): upgrade the table metadata stored by an older copy of the package
* test(modifiers): pin lookups by names shared with Object.prototype members * fix(modifiers): look up a container entry by own key
* test(encryption): pin which stored objects are revived as dates * fix(encryption): revive only the date marker the encoder writes * refactor(encryption): type the stored values the date reviver reads
…ng it (#54) * test(metadata): pin the metadata of subclasses of a table * fix(metadata): copy the metadata a subclass inherits instead of sharing it * test(metadata): pin the schema binding of a subclass built before RegisterSchema * fix(metadata): bind a subclass to the schema registered under its schema name * refactor(modifiers): copy the modifier lists of a parent from the record helpers * refactor(modifiers): keep listsCopied private to the record helpers
* test(modifiers): pin modifier fields and events named like Object.prototype members * fix(modifiers): look up modified fields and event names by own key * test(modifiers): pin that a modifier on a field named __proto__ is refused * fix(modifiers): refuse a modifier on a field named __proto__ * refactor(modifiers): keep the refused-field check with the record helpers
* docs: typecheck every example and drop hand-written version prose * fix(docs): stop the docs program from emitting declarations
…t contracts (#62) * test(modifiers): pin modifier fields and events named like Object.prototype members * fix(modifiers): look up modified fields and event names by own key * build: run pnpm 10.33.0 pnpm before 10.20 fails a frozen install of some file: tarball dependencies (ENOENT in the store index), which the campaign tarball pins need. * build(deps): test against the interface-database 0.3.0 tarball Producer: AntelopeJS/interface-database feat/typed-query-stages at 4939b45, version 0.3.0. The devDependency range ^0.1.11 excludes 0.3.0, so the contract suite never ran against it. * test: read the schema stage's id through interface-database 0.3.0's stage union The recorded options are typed per stage now, so the tests match the schema stage and its id instead of reading options.id off any stage. * test(modifiers): pin that a modifier on a field named __proto__ is refused * fix(modifiers): refuse a modifier on a field named __proto__ * refactor(modifiers): keep the refused-field check with the record helpers * test: read the schema stage's id through interface-database 0.3.0's stage union in the subclass binding tests The subclass binding tests landed after the 0.3.0 tarball pin was written, and read options.id off any stage; the recorded options are typed per stage now. * feat(database-decorators)!: type the fixture generator by its table class Fixture now checks that the class it is called with is the decorated class or a subclass of it, so it calls the generator with that class without an assertion. The stored generator gives plain objects instead of records of unknown values. BREAKING CHANGE: DatumGeneratorOutput is `Row | Row[] | undefined` over objects (`Row = object` by default) instead of records of unknown values. * feat(database-decorators)!: type the model's schema name and index lookups BasicDataModel keeps the schema name its table class registers into, which is undefined for a table class without @RegisterTable; the type now says so instead of asserting a string. getBy takes an index named by a string field of the table and keys typed as interface-database's selection keys. BREAKING CHANGE: DataModel.schemaName is `string | undefined`. getBy's index is `Extract<keyof T, string>` and its keys are `IndexKey` (a value proxy or a string, number or boolean), no longer `any`. * feat(database-decorators)!: type the auto-date event handlers by the field they stamp BREAKING CHANGE: AutoDateModifier.insert and update take `(object: Partial<Record<F, Date>>, field: F)` instead of a record of unknown values and a string. * feat(database-decorators)!: refuse @Index on a symbol-keyed field An index names a database field, so the decorator throws for a symbol key instead of recording the symbol as a string. BREAKING CHANGE: @Index on a symbol-keyed property throws at class declaration. * feat(database-decorators)!: drop the once-used type parameters of getModifiedFields and toDatabase getModifiedFields takes any modifier class and toDatabase takes the table instance as `{ constructor: any }`. getBy's IndexKey is derived from Table.getAll instead of interface-database's common subpath. BREAKING CHANGE: getModifiedFields has one type parameter (the object's type) instead of two; toDatabase has none. * feat(database-decorators)!: type the stored unlock arguments as unknown values The arguments a modifier is unlocked or locked with are whatever the caller passed for it, so ModifiersDynamicMetadata.fields records them as unknown arrays and the engine no longer spreads `any` into modifier methods. BREAKING CHANGE: ModifiersDynamicMetadata.fields is `Record<string, Record<string, unknown[]>>` instead of `any[]` lists. * feat(database-decorators)!: record each modifier event with its handler attachModifier now stores the modifier method it found for an event next to the field and the modifier, so triggerEvent calls that method with the modifier as `this` instead of looking it up by name through two assertions. BREAKING CHANGE: the entries of ModifiersStaticMetadata.events are `[field, modified, handler]`, with the new exported ModifierEvent type for the handler. * build: set the package version to 0.2.0 * chore: lower the ratchet ceilings to the findings left after the contract changes * test: assert the error type of the symbol-keyed index refusal, not its wording * build(deps): test against interface-database 6bef278
… unknown local (#66)
…nd give (#67) * feat(database-decorators)!: name the row forms the conversions read and give A table row has three forms: the instance, the plain form and the stored form. The conversions typed the last two as `any` or open dictionaries, which hid what every caller already relies on. They now name them: - `PlainData<T>` is what `fromPlainData` reads: every field optional and possibly partial, a field under a container modifier possibly its value per key, the plain form 40 consumer calls already write. - `PlainRow<T>` is what `toPlainData` gives: the set fields of `T` by name. - `StoredRow<T>` is what `toDatabase` gives: typed `T` as `Table<T>` reads it, with `_internal` declared. - `fromDatabase` takes the row as `Table<T>` types it, and gives it back with the class's prototype. - `update(obj)` without an id takes `_id` in its type, as the docs said. - `DatumStaticMetadata.primary` is the literal `"_id"`: nothing writes it. - `unlockrequest` reads the stored form through `ValueProxy#cast` instead of an `any`; its signature keeps its answers. `_internal.data`, `floating` and the modifier state stop being `any`: what they hold is known to the modifiers that wrote them, so they read as `unknown`. BREAKING CHANGE: `fromDatabase`, `fromPlainData`, `toDatabase`, `toPlainData` and the matching `BasicDataModel` statics no longer accept or return `any`. `triggerEvent` loses a type parameter nothing reads. `primary` no longer takes another string. * feat(database-decorators)!: keep reads of a stored row unchecked `fromDatabase` and the model's static take what the database answered, as before. A typed parameter measured +2 `no-unsafe-*` rows in interface-data-api and three compile breaks, and it cleared nothing here: the two rows that stay are the driver boundary, and an `as` in their place would only trade one finding for another. `triggerEvent` keeps its type parameter for the same reason: without it, that `any` copy is a new `no-unsafe-argument`. `StoredRow<T>` is no longer `T`: a stored row has no prototype, so typing it as the class made every spread of it a `no-misused-spread`. It now reads as the set fields. The model's own writes keep the `T` they build. * fix(modifiers): keep assigning a floating value by a plain assignment's rules * chore(suppressions): lower the SAFETY budget to the comments left
… typed query operands (#70) * build(deps): pin interface-database to the query value tarball * feat(database-decorators)!: take a text field in unlockrequest `unlockrequest` read the proxy of a field by `keyof T`, which includes numbers and symbols. A query operand is a name or a number held in a query value, never a symbol, so the field is a text key. BREAKING CHANGE: `unlockrequest` takes `K extends keyof T & string`. * chore(ratchet): leave the ceilings to the ceiling pass * build(deps): pin interface-database to the structural operand tarball * build(deps): pin interface-database to the IsQueryValue tarball * build(deps): pin interface-database to the type-only tarball * fix(database-decorators): keep unlockrequest's published key constraint Narrow the key to text inside unlockrequest instead of tightening K, so interface-data-api's Validation.UnlockRequest<T, K extends keyof T> keeps compiling.
…what a decorator holds (#71) * refactor(database-decorators): build on interface-core 0.4's typed decorator targets The table modifier decorators get a DecoratorTarget, whose constructor is a Function, so they attach through an internal attachModifierTo that takes the class as a Function and the field as a property key; the public attachModifier keeps its typed signature and delegates to it. RegisterTable's handler receives a Class<Table> through MakeClassDecorator's class parameter. unlockrequest takes any Constructible table, since it only reads the table's modifier metadata, so a caller holding a Class<object> no longer has to claim the row type. Building a modifier's field entry moves to internal/records. Pins interface-core to the 6a8b526 tarball (0.4.0). * feat(database-decorators): let attachModifier take the class a decorator receives attachModifier takes the table class as a Function and the field as a property key, what it reads (the class's metadata, name and prototype), so a property decorator can pass its DecoratorTarget's constructor and key as they come, as the docs show. The internal attachModifierTo this branch added is gone: the table modifiers call attachModifier again, and the package gains no runtime export.
* chore(ratchet): delete the guardrail ratchet * build(sync): drop the ratchet step
* docs(readme): use one Discord invite (#68) * docs(github): send questions and ideas to Discord (#76) * fix(fixtures): let two processes register a fixture on an empty table (#74) * test(fixtures): cover two processes registering a fixture at once * fix(fixtures): let two processes register a fixture on an empty table * docs(fixtures): keep to what the fixture insert checks * Merge commit from fork * fix(model): keep modifier data on a partial update of another field A modifier event creates an empty `_internal` on the instance. The update writes that key as one value, so it erased what the row stored there. * fix(hash): hash values with scrypt by default `@Hashed()` now stores `$scrypt$ln=15,r=8,p=1$<salt>$<key>`. Rows in the earlier digest format still verify, and `isHashOutdated` flags them so that a caller can write them again after a successful test. `testHashAsync` runs the test on the thread pool. An explicit `algorithm` keeps its digest format. * fix(hash): raise the default scrypt cost to p=3 N=2^15, r=8, p=3 is the minimum OWASP lists for that N. It takes about 150 ms and the same 32 MiB as p=1. * test(hash): give suites that spend scrypt runs a longer limit At p=3 a test with several runs passes mocha's 2 s limit on a busy machine. * fix(hash): refuse a stored hash outside the cost bounds A stored hash names its own cost, so a tampered row could ask for an expensive run. Salt and key must take 16 to 64 bytes, the memory 128 MiB at most and p 16 at most. A row outside that, or with an N that r cannot hold, verifies nothing and no longer throws. * chore(release): v0.1.12 * docs(hash): mark the stored-hash upgrade snippet as a fragment --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* docs: pass the database-decorators docs to the docs standard * docs: turn on the docs standard * docs: say when fromDatabase returns undefined and when a digest test runs scrypt
|
| GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
|---|---|---|---|---|---|
| 39448498 | Triggered | Generic Password | 4a959c7 | src/tests/helpers/hash-rows.ts | View secret |
| 39448499 | Triggered | Generic Password | 4a959c7 | src/tests/helpers/hash-rows.ts | View secret |
🛠 Guidelines to remediate hardcoded secrets
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secrets safely. Learn here the best practices.
- Revoke and rotate these secrets.
- If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.
To avoid such incidents in the future consider
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.
Upd4ting
force-pushed
the
chore/land-campaign-2026-11-04
branch
from
November 4, 2026 19:51
3176468 to
69ef969
Compare
This was referenced Nov 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lands
campaign/integrationat fa91e2d onmain. Every change on that branch landed through a verified pull request. The tree of this pull request equalscampaign/integration; the merge ofmainonly joins the histories, sincecampaign/integrationalready contains every change ofmainup to 82ae1bb. No package is published by this merge.