toga-ai 1.0.839 → 1.0.840

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.
@@ -6,7 +6,7 @@ project: API
6
6
  client: shared
7
7
  type: feature
8
8
  status: active
9
- updated: 2026-09-17
9
+ updated: 2026-09-18
10
10
  owners: [tcox, bala, apeterson, jcardinal, rgirish]
11
11
  files:
12
12
  - api2/Component/Api/V2/V2.php
@@ -364,6 +364,23 @@ successfully.
364
364
  > `group=_status` is separately known to fail. And `where` still never prunes a nested child array
365
365
  > (see below).
366
366
 
367
+ #### ⚠ `in` instead of an OR-chain of `contains` shortens the SQL - it does NOT make the filter fast
368
+
369
+ A calculated field's expression is inlined per row, so **no operator makes it indexable**. Swapping
370
+ an OR chain of `contains` for one `in` clause only shrinks the query text.
371
+
372
+ Measured on sandbox-client 2026-09-18 (TRUE-81379, Compass approvals list): after the blox `in`
373
+ serializer shipped, the request sends the single clause
374
+ `where=(_status:in:pendingApproval:pendingInitialApproval)` - and the endpoint still takes
375
+ **14.66 s** (`GET /v2/sales-orders?recordsPerPage=15&page=1&sort=-number&...`, plus joins on
376
+ Addresses and ojoins on Locations/Contacts/Users). `_status` on SalesOrders is calculated, so every
377
+ sales order (~11,000 in `pendingApproval` alone) is evaluated before paging - strongly supported,
378
+ but not yet proven against the generated SQL.
379
+
380
+ **Do not read `in` in the network tab as "the slow filter is fixed."** Making it fast means taking
381
+ the calculated field out of the filter path (a stored/indexed status column, or a pre-filtered set),
382
+ not tuning the serializer.
383
+
367
384
  ## Encoding rules (the query string is never urldecoded at parse time)
368
385
 
369
386
  - Encode a literal `%` in a LIKE pattern as **`%25`**.
@@ -540,6 +557,9 @@ If you need the behaviour, loop uuids client-side. Point 3 is the durable, non-o
540
557
  [V2 request logging](request-logging.md).
541
558
 
542
559
  ## Change history
560
+ - 2026-09-18 — Recorded that swapping an OR-chain of `contains` for a single `in` on a
561
+ calculated field only shortens the SQL text and does not speed it up: the Compass approvals list
562
+ (`_status:in:...`) still takes 14.66 s with the `in` clause live (TRUE-81379). (apeterson)
543
563
  - 2026-09-17 — Documented that **bulk `DELETE` by `where` is implemented but unused and unsafe to
544
564
  adopt**: the branch is real (`V2.php:5554` / `:5697` / `:5740`, returns `meta.deletedRecordCount`)
545
565
  but has zero callers, is non-atomic with no rollback, and — the decisive part — **zero matching
@@ -6,7 +6,7 @@ project: TOGa Blox
6
6
  client: shared
7
7
  type: workflow
8
8
  status: active
9
- updated: 2026-09-16
9
+ updated: 2026-09-18
10
10
  owners: [jcardinal, apeterson, tcox, rgirish]
11
11
  files:
12
12
  - toga-blox/.github/workflows/publish.yml
@@ -32,6 +32,10 @@ Core model:
32
32
  - **Version derivation (CI owns the suffix; dev owns only the base).** CI reads `version` from `package.json`, **strips any `-<suffix>`**, does **`patch + 1`**, then appends `-<mode>.<GITHUB_RUN_NUMBER>`. Base `1.0.317` on `_sandbox-client` run 104 publishes `1.0.318-sandbox-client.104`. The developer controls only the BASE version committed in `package.json` on the feature branch. **Never hand-write the `-<mode>.N` suffix** — CI generates it. There is no manual `npm publish`; CI is the only publisher.
33
33
  - **A GitHub branch and an npm channel are unrelated.** Creating a `_<mode>` branch in a *consuming app* repo (e.g. `toga2-commerce`) only tells Amplify what to build — it does **not** create a blox channel. A channel exists **only** when this repo (`toga-blox-npm`) publishes with `npm publish --tag <mode>`, which `publish.yml` now does automatically for any `_<mode>` branch.
34
34
 
35
+ - **The trailing `.N` is the shared `GITHUB_RUN_NUMBER`**, not a per-package counter. It counts runs across **all** `_*` branches, so gaps in a channel's sequence (e.g. `.164`–`.167` missing) are runs that published other branches — never a failed or lost publish.
36
+ - **CI never commits the version back.** Step 9 runs `npm version --no-git-tag-version`, so `package.json` in git stays at the base (e.g. `1.1.9`) forever and never matches what npm shows. That mismatch is by design.
37
+ - **⚠ Never hand-bump `package.json` to a published prerelease value.** Committing `1.1.10-sandbox-client.169` makes CI strip the suffix, read the base as `1.1.10`, and publish `1.1.11-...` next run — silently moving the base a patch. Edit `package.json` only to deliberately move the base (e.g. `1.1.9` → `1.2.0`).
38
+
35
39
  **What was removed (and why it's safe):** the old workflow hardcoded a branch list (`_production/_gamma/_beta/_qc-security`) with a production special case: `_production` published dist-tag `latest` with a plain (non-prerelease) version, committed the bump back, and git-tagged. **All gone.** Consequence: the workflow no longer maintains the `@latest` npm tag. Fine because consumers never install bare `npm install @agilant/toga-blox`; they install by explicit `@<mode>` channel (commerce's `amplify.yml`) or by a pinned/ranged version in `package.json`.
36
40
 
37
41
  ## Steps
@@ -74,6 +78,21 @@ Practical consequence: a consumer's `.npmrc` needs the FontAwesome registry line
74
78
 
75
79
  **⚠ Never commit a token VALUE in `.npmrc`.** Live FontAwesome tokens have been found **committed** in `toga25-supply/.npmrc` and `info/.npmrc`, and one was pushed in `bdr` commit `88809c3`. Treat every token found this way as compromised and rotate it. The correct shape is an env-var placeholder resolved at build time — exactly what blox's own `publish.yml` does (see the "Secret hygiene done right" gotcha below). This is the same violation recorded in [`../../../standards/frontend.md`](../../../standards/frontend.md); what is **new here is that only the FontAwesome token was ever needed** — the npmjs token in those files bought nothing.
76
80
 
81
+ ### You cannot publish blox from a laptop — and `npm login` makes it worse
82
+
83
+ Publishing **is** the push to a `_*` branch; there is no supported local path.
84
+
85
+ - The publish credential is the GitHub Actions secret **`NPM_TOKEN`** (granular, bypass-2FA), consumed as `NODE_AUTH_TOKEN`. It lives only in GitHub secrets — never on a laptop.
86
+ - npm requires **either** an interactive 2FA code **or** a granular bypass-2FA token to publish. The `agilant-blox` npm account has **no 2FA**, so the bypass token is the only route.
87
+
88
+ | Symptom | What it means |
89
+ |---|---|
90
+ | `403 Forbidden - PUT .../@agilant%2ftoga-blox … Two-factor authentication or granular access token with bypass 2fa enabled is required` | You are on a web-session token — which is what `npm login` writes over the `//registry.npmjs.org/:_authToken=` line in `~/.npmrc`. Not publishable. |
91
+ | `404 Not Found - PUT` | No token at all; npm returns 404, not 401, for an unauthenticated publish. Easy to misread as "bad version". |
92
+ | `npm whoami` prints `agilant-blox` | Proves only that the token can **read**. Says nothing about publish rights or the bypass flag — never treat it as proof publishing will work. |
93
+
94
+ Dates: the **August 2026** npm change removed 2FA-bypass for *account and package management* only (token creation, maintainer/org changes) — publishing was unaffected. Bypass-2FA tokens lose **direct publish around January 2027**; move `publish.yml` to trusted publishing (OIDC) or staged publishing before then. That is a CI change, since CI is already the only publisher.
95
+
77
96
  ## Gotchas
78
97
 
79
98
  - **⚠ There is a STALE UNDERSCORED dist-tag on the registry — `_sandbox-client` (with the underscore) is NOT the channel.** Re-verified 2026-09-02, the registry still carries **both** `_sandbox-client` = `1.0.316-sandbox-client.1` (vestigial, predates the current pipeline; it has **not** moved in over a month) **and** `sandbox-client` = `1.1.2-sandbox-client.142` (the live channel head). Branch `_<mode>` maps to channel `<mode>` with the underscore **stripped** (same convention as `amplify.yml`), so the **branch** `_sandbox-client` tracks the **tag** `sandbox-client`. Asking npm for "the latest `_sandbox-client` tag" literally installs something **141 publishes behind**. Always resolve the head with `npm view @agilant/toga-blox dist-tags` and install the underscore-less name.
@@ -88,7 +107,7 @@ Practical consequence: a consumer's `.npmrc` needs the FontAwesome registry line
88
107
  3. No feature branch pending merge **touches the `version` line** — normally true, because feature branches never edit it.
89
108
  If any one fails, bump on the feature branch instead. Note the bump commit lands *only* on `_sandbox-client` and is never merged back, which is precisely what generates the "N behind" release plumbing.
90
109
  - **`gh` is not installed on every dev machine.** The skill's `gh run watch` monitoring step simply does not work there. Fall back to polling the registry: `npm view @agilant/toga-blox@sandbox-client version` (or `npm dist-tag ls @agilant/toga-blox`) until the new version appears — the registry is the authoritative confirmation anyway.
91
- - **Consuming apps pin exactly, so a publish is only half the deploy.** After `1.0.334-sandbox-client.136` shipped, `toga25-supply` on `_sandbox-client` was still pinned to `1.0.333-sandbox-client.134` and needed a pin bump + reinstall. Likewise the feature branch stays at its old base version after the bump lands on `_sandbox-client` expect the two to be out of step and don't read it as a problem.
110
+ - **A publish is only half the deploy and the consumer must depend on the LITERAL dist-tag.** In `toga25-supply/package.json` the dependency is the bare tag string (`"@agilant/toga-blox": "sandbox-client"`), **not** a version range. `npm install @agilant/toga-blox@sandbox-client` rewrites it to a `^` range, which then stops following base bumps — re-set the literal tag, re-run `npm install`, commit `package-lock.json`. Verify what is installed with `node -p "require('./node_modules/@agilant/toga-blox/package.json').version"`. Exact pins drift: branch `TRUE-81379` was pinned to `1.1.3-production.166` while `node_modules` held `1.1.10-sandbox-client.163` check this first when a fix "works locally but not after deploy". Likewise the feature branch keeps its old base version after a bump lands on `_sandbox-client`; that is expected.
92
111
  - **⚠ Credentials have been found in the local git remote URL.** Verified 2026-08-26: the `origin` remote for the `toga-blox-npm` checkout had a **GitHub PAT embedded in plaintext in the URL** (visible to anything that runs `git remote get-url origin`, and to any tool that reads `.git/config`). Check for this and re-point the remote at SSH or a credential helper; treat any token found this way as compromised and rotate it. This is the local-config sibling of the committed-`.npmrc` violation already recorded in `../../../standards/frontend.md`.
93
112
  - **FontAwesome v7 `style`-prop TS2322** (fixed 2026-07-21 in `getFontAwesomeIcon.tsx`, and a reusable pattern for any consumer). FA v7 types the `FontAwesomeIcon` `style` prop as `CSSProperties & CSSVariables`, where `CSSVariables` requires a `--fa-*` custom-property index signature that plain `React.CSSProperties` lacks. Cast the passed style to `React.CSSProperties & Record<\`--${string}\`, string>` — the value type must be `string` (**not** `string | number`; `CSSVariables` requires `string`). Runtime and function signature are unchanged, so it is safe for the ~40 consumers.
94
113
  - **The `_production`/`_beta` build copies only `.scss` — a plain `.css` component stylesheet is silently dropped from the tarball.** On `_production` and `_beta` the `build` script is `tsc && copyfiles -u 1 "src/**/*.scss" dist`: `tsc` compiles a component's `import "./Foo.css"` into the emitted JS, but `copyfiles` never ships the `.css`, so the published package contains JS importing a file that isn't in the tarball. Consumers then fail their Vite/Rollup build with `Could not resolve "./Foo.css"` (seen with `EnvironmentBadge` in `@agilant/toga-blox@beta` 1.0.316-beta.108, breaking `toga2-commerce`). **Convention on the prod/beta build: author component stylesheets as `.scss`, never `.css`** (a flat `.css` file is valid SCSS as-is, so renaming is the zero-risk fix — no build-script change). Note the build description in `architecture.md` (copies `*.scss/*.css/*.module.css`) reflects the in-progress `feature-new-table` branch, **not** the current `_production`/`_beta` build; that feature branch is not to be merged to prod/beta just to pick up the wider copy glob.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.839",
3
+ "version": "1.0.840",
4
4
  "description": "TOGA Technology Team Claude Knowledge System — shared AI coding harness with skills, knowledge base CLI, and project installer for Claude Code.",
5
5
  "keywords": [
6
6
  "claude",