Skip to content

feat(rules): portable API schemas and private declarations - #17

Merged
agjs merged 1 commit into
mainfrom
fix/product-feedback-rules
Sep 14, 2026
Merged

agjs merged 1 commit into
mainfrom
fix/product-feedback-rules

Conversation

@agjs

@agjs agjs commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Findings 21, 24, 35, 37, 38 and 51 from the Tinkercaster build (boringstack-xyz/boringstack#455 ledger) fixed at the rule level.

elysia/portable-schema-types (new, minor). The API's TypeBox schemas are published as OpenAPI and turned into the UI client's types, and three Elysia shapes validate fine but come out wrong on the other side. Reproduced against Elysia 1.4 + @elysiajs/swagger 1.3:

Shape Published / inferred as Replacement
t.Integer() anyOf [{type:"string",format:"integer"},{type:"integer"}], client types string | number Type.Integer() from @sinclair/typebox
t.Tuple([...]) draft-4 items: [...], client widens to T[] t.Array() or a named t.Object()
t.Union(values.map(...)) static type undefined t.UnionEnum([...values])

Scoped to **/*.schemas.ts by default (option fileGlob), so env parsing, which wants the coercion, is untouched. Added to the recommended config.

module-boundaries/single-semantic-module gains ignorePrivateDeclarations (default false, minor). When on, only exported declarations are classified: a non-exported config object, render helper or private class next to the hook or component that uses it does not give the module a second category. Two exported categories still conflict, and an exported constant is still a constant.

Test plan

pnpm -r build && pnpm -r test: elysia 127 tests (new rule: 4 valid, 4 invalid, plus plugin-shape and recommended-config coverage), module-boundaries 62 tests (option on/off, exported constant still reported, two exported categories still reported). Docs and changesets for both.

- react-component-architecture/component-folder-structure: a .tsx file
  that exports nothing is an internal helper of the component beside it
  and owes no siblings of its own.
- audit-log/mutating-service-must-audit: only the public surface is
  checked; module-private functions and private/protected/#name methods
  are body of the audited method. includePrivate restores the old scan.
- drizzle-conventions/no-raw-sql-outside-allowlist: templates whose text
  is only arithmetic around column references (the atomic increment) are
  allowed; allowColumnArithmetic: false disables it.

Each ships with rule-tester cases, docs and a changeset.
agjs added a commit to boringstack-xyz/boringstack that referenced this pull request Sep 14, 2026
…itself

- Session in lib: useMe, IMe, isAuthenticatedMe and SESSION_QUERY_KEYS
  move to src/lib/session so every feature reads the current user without
  a cross-feature exception; auth consumes them too, the allow-list keeps
  only accounts -> auth for the MFA settings section. Reference UI
  templates follow.
- Cache generations: bumpGeneration / readGeneration / generationScopedKey
  give seeds, publishes and migrations a way to drop a namespace at once;
  regression proves old keys become unreachable.
- Guides: relational row typing and numeric/bigint strings (drizzle),
  portable API schemas (typescript, api-client), cache namespaces, grouped
  store selectors, session module (state-management, routing).
- Dead-key lint message says which template literals it can follow.
- Ledger rows 23, 24, 26, 36, 37, 38, 51, 63, 78, 80 record the fix or
  the upstream rule (boringstack-xyz/eslint-plugins#17).
@agjs
agjs merged commit 12fd7ee into main Sep 14, 2026
2 checks passed
@github-actions github-actions Bot mentioned this pull request Sep 14, 2026
agjs added a commit that referenced this pull request Sep 14, 2026
audit-log 0.2.0, drizzle-conventions 0.2.0 and react-component-architecture
0.3.1 shipped from #16; the squash of #17 brought their changeset files
back, so the release workflow versions again instead of publishing the
pending elysia and module-boundaries 0.2.0.
agjs added a commit to boringstack-xyz/boringstack that referenced this pull request Sep 14, 2026
* fix: address product setup and agent validation feedback

* fix(agent): copy UI dependency patches into the isolated candidate image

The isolated evaluation image installs apps/ui from package.json and
bun.lock alone. With patchedDependencies present, a frozen install
aborts on the missing patch file, which failed the agent verification
contract job. Copy the patches directory before installing and assert
in a unit test that every patched dependency is copied ahead of the
install step.

* fix(ui): keep the ESLint cache and invalidate it on dictionary changes

Removing --cache made every lint run cold. ESLint keys its result cache
on a hash of each file's resolved config, so the config now carries a
sha256 digest of every English dictionary in settings; editing a
dictionary changes the hash and re-lints every file. A regression runs
ESLint twice with --cache against a shrinking dictionary and shows the
deleted key is reported with the digest and hidden without it.

* fix(ui): drop an unused import and format the ESLint config

The cache regression built its digest inside a generated config string,
so the createHash import in the test itself was unused; the config edit
also missed a Prettier pass.

* fix(ui): take the plural-aware i18n lint rule from the released plugin

@boring-stack-pkg/eslint-plugin-i18n-keys 0.1.3 resolves i18next count,
ordinal and context suffixes upstream (boringstack-xyz/eslint-plugins#10),
so the Bun patch of the published dist, its patchedDependencies entry and
the COPY patches lines in the three Dockerfiles go away. The installed
plugin regression in tests/lint-meta keeps guarding the behaviour.

* chore(lint): take three rule fixes from the released plugins

react-component-architecture 0.3.1 exempts .tsx files that export
nothing from component-folder-structure; audit-log 0.2.0 checks a
service's public surface only; drizzle-conventions 0.2.0 accepts column
arithmetic such as the atomic increment. Guides describe the accepted
shapes and the feedback ledger closes rows 40, 65 and 82 as implemented
upstream (boringstack-xyz/eslint-plugins#15).

* feat: close the remaining product-feedback rows the template can fix itself

- Session in lib: useMe, IMe, isAuthenticatedMe and SESSION_QUERY_KEYS
  move to src/lib/session so every feature reads the current user without
  a cross-feature exception; auth consumes them too, the allow-list keeps
  only accounts -> auth for the MFA settings section. Reference UI
  templates follow.
- Cache generations: bumpGeneration / readGeneration / generationScopedKey
  give seeds, publishes and migrations a way to drop a namespace at once;
  regression proves old keys become unreachable.
- Guides: relational row typing and numeric/bigint strings (drizzle),
  portable API schemas (typescript, api-client), cache namespaces, grouped
  store selectors, session module (state-management, routing).
- Dead-key lint message says which template literals it can follow.
- Ledger rows 23, 24, 26, 36, 37, 38, 51, 63, 78, 80 record the fix or
  the upstream rule (boringstack-xyz/eslint-plugins#17).

* fix(agent): reference UI needs no auth allow-list entry; Docker errors carry a redacted stderr tail

The reference UI generator patched the cross-feature allow-list at the
["dashboard", "auth"] anchor to add projects -> auth; with useMe in
@/lib/session the entry is unnecessary and the anchor is gone, which
failed the isolated positive control. The isolated Docker helper now
appends the last 600 characters of stderr with every argument value
redacted, so the next failure of this kind is readable in CI.

* chore(lint): enable portable schema types and private declarations from the released plugins

elysia 0.2.0 adds portable-schema-types, on for every *.schemas.ts;
module-boundaries 0.2.0 adds ignorePrivateDeclarations, on for the UI so
private helpers and constants stay next to the hook or component that
reads them. Ledger rows 21, 35 and 51 close as implemented upstream.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant