Skip to content

fix: the 2026-10-17 review's medium findings (reinstall approval, setup tests, pagination, AppService scope) - #6

Merged
jschuller merged 5 commits into
mainfrom
fix/review-mediums-2026-10-17
Oct 22, 2026
Merged

jschuller merged 5 commits into
mainfrom
fix/review-mediums-2026-10-17

Conversation

@jschuller

Copy link
Copy Markdown
Owner

Fixes four open medium findings from the 2026-10-17 repository review. They are build-verified only: no instance was used. The instance steps are below, and the owner decision is listed at the end.

Finding Fix Commit
The deploy skill let an agent run --reinstall after only telling the user Both skill copies, AGENTS.md rule 2 and TROUBLESHOOTING.md (both places) now say the agent waits for explicit approval: --reinstall deletes the app's table records 4f3bf4b, ee6cfd3
setup.mjs had no tests or CI coverage npm test (tests/setup.test.mjs) runs setup on temp copies, with and without git. It checks the rename, the new scopeId, the lockfile, CHANGELOG and keys reset, and the refusals (unsafe names, a dirty tree, a second run without --force that writes nothing). The tests skip in apps made from the template. CI runs them. The temp repos ignore global and system git config and hooks 60f7344, ee6cfd3
Offset pagination duplicated rows, and a change dropped the loaded pages Pages merge by sys_id, and every loaded page reloads after a create, update or delete. A "Load more" answer that a reload overtook is dropped. The server breaks sys_created_on ties by sys_id a296bd9
Top-level var constants could collide across Script Includes The constants are wrapped, so AppService is the only global the file declares. The built record's XML outside <script> is byte-identical to main's (api_name, access, the callable flags) c70cfd1

Verified:

  • npm run lint and npm run build:ci (frozen keys; keys.ts unchanged) pass.
  • npm test passes 39/39 on Node 20.18.0, 20.20.2, 22.23.3 and 26.
  • sync:skills --check passes.
  • A pre-push review re-checked each fix, including the ES5 parse and setup on a scratch copy (11/11 tests in the derived app). It found two problems, fixed in ee6cfd3:
    • the quoted test glob failed on Node 20;
    • one --reinstall mention had no approval rule.
  • gitleaks is clean.

Instance steps (not run):

  1. npm run build, then npm run deploy -- --auth <alias>, then npm run test:instance -- --auth <alias>. The ATF suite shows AppService still resolves and validates through the wrapper.
  2. Open x_snc_example_app.do with more than 50 items and click "Load more".
  3. From another session, create an item, then click "Load more" again: no row appears twice.
  4. Edit an item: every loaded page stays.

Known limits (follow-ups):

  • Offset paging still drifts when 50 or more rows are created between two "Load more" clicks. Keyset paging would fix that.
  • Clicks during a reload are dropped, not queued.
  • release.yml doesn't run npm test.

Owner decision (not applied)

  • The Table API path skips AppService's validation (example-item.now.ts:9, 27; app-acls.now.ts:15-20). Turn off allowWebServiceAccess, or enforce the rules on the platform (a before insert/update business rule or a data policy) with an ATF step for the Table API path?

--reinstall uninstalls the app first and deletes everything on the instance
that is not in source, including the records in the app's tables. The
deploy-and-verify skill let an agent retry with it after only telling the
user. The skill (both copies, via npm run sync:skills), AGENTS.md rule 2 and
TROUBLESHOOTING.md now require the user's explicit approval first.
setup.mjs is the first command every adopter runs and had no tests. Add
npm test (node --test) and tests/setup.test.mjs, which runs setup.mjs on
temporary copies of the repository, as a git checkout with an origin and as
a plain directory, and checks:

- the scope and name rewrite (no x_snc_example left outside the files setup
  skips), the new scopeId, package.json, the lockfile root, CHANGELOG.md
  and the removal of src/fluent/generated/;
- the .gitignore-aware fallback walk outside git;
- the refusals: unsafe scopes and names, a dirty tree, and a second run
  without --force, which must write nothing; --dry-run writes nothing.

The setup tests skip themselves once the app is set up, and setup.mjs
leaves tests/setup.test.mjs as written, so derived apps keep a passing
npm test. CI runs npm test in the build job; docs list the command.
Offset pages over a newest-first list shift when rows are created between
requests, so "Load more" could repeat the last shown row and give React
duplicate keys; every create, update or delete reloaded only the first page
and dropped the rest.

- src/client/services/pagination.js: mergeById (one row per sys_id, the
  newer copy in place) and loadPages (reload N pages from the top).
- App.jsx merges each "Load more" page by sys_id, counts loaded pages and
  reloads all of them after a change; "Load more" waits for a running
  reload and drops an answer that a reload overtook.
- AppService.listItems orders sys_created_on ties by sys_id, so rows created
  in the same second do not move between pages.
- tests/pagination.test.mjs covers the helpers and both scenarios.

Same API (limit and offset). Built and unit-tested; it needs an instance to
observe in the UI page.
FP, ITEM_TABLE, CATEGORIES, MAX_NAME and the other limits were top-level
vars in the Script Include, which may be shared with other Script Includes
in the same transaction: a second file declaring CATEGORIES or MAX_NAME
could change AppService's validation depending on load order.

Wrap AppService.server.js in a function that returns the class, so
AppService is the only name it declares. The compiled sys_script_include
record differs only in its script text. A vm comparison of the old and new
file over create/update/delete/list/readBody inputs gave identical results.
tests/app-service.test.mjs checks that only AppService is declared, that
colliding globals declared before or after it change nothing, and the list
query. AGENTS.md rule 5, the Script Include recipe and TROUBLESHOOTING.md
teach the pattern. Not yet run on an instance.
… the approval rule

The quoted test glob needs Node 22's own glob expansion; unquoted, the shell expands it on Node 20. TROUBLESHOOTING's cross-scope section now carries the same approval caveat, and the setup tests' temp repos ignore global and system git config and hooks.
@jschuller
jschuller merged commit dafd056 into main Oct 22, 2026
3 checks passed
@jschuller
jschuller deleted the fix/review-mediums-2026-10-17 branch October 22, 2026 02:25
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.

2 participants