Conversation
## Summary - move GitHub repository, issue, badge, contribution, Release, and raw-content coordinates to `bytefolk` - update the npm bootstrapper default Release repository and its regression coverage - preserve `@fullstack-ai-infra/mem-mcp`, `io.github.fullstack-ai-infra/mem-mcp`, and existing cache paths ## Cutover gate This PR prepares the repository for the organization handle cutover tracked by bytefolk/.github#20. Do not merge before the organization rename window. ## Validation - `cd npm && npm test` — 34 passed, 1 Windows-only test skipped on macOS - `bash scripts/validate_release_version.sh 0.1.1` — passed - `git diff --check` — passed - old GitHub URL/API/raw/SSH owner-coordinate scan — 0 matches - stable npm scope, MCP identity, and cache paths — retained ## Rollback Before cutover, revert this commit if the rename window is cancelled. After cutover, GitHub redirects provide a safety net, while the canonical coordinates in this PR should remain. Refs bytefolk/.github#20
#152) Adds an `npm-publish` job to release.yml implementing G4 via npm OIDC Trusted Publishing (founder 08-30 ruling). - `permissions: contents: read` + `id-token: write` - `cd npm && npm publish --provenance --access public` - No `NPM_TOKEN` / `NODE_AUTH_TOKEN` — auth is exchanged from the GitHub OIDC id-token against the npmjs Trusted Publisher (org=fullstack-ai-infra / repo=mem / workflow=release.yml), which the founder configures on npmjs.com. - checkout pinned to the same SHA as existing steps; node 22; `needs: [release]` so it runs after the GitHub Release (G1) exists and install.js can pull binaries. Dependency order held: G1 (v0.1.0 GitHub Release) first; install.js pulls binaries from the Release at install time. Refs #104
Bumps [browserslist](https://github.com/browserslist/browserslist) from 4.28.2 to 4.28.8. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/browserslist/browserslist/releases">browserslist's releases</a>.</em></p> <blockquote> <h2>4.28.8</h2> <ul> <li>Fixed <code>including kaios</code> in baseline queries (by <a href="https://github.com/Jaybhade"><code>@Jaybhade</code></a>).</li> </ul> <h2>4.28.7</h2> <ul> <li>Improved parsing performance.</li> <li>Fixed unbounded memory growth (by <a href="https://github.com/alanturing881"><code>@alanturing881</code></a>).</li> <li>Fixed prototype write issue (by <a href="https://github.com/alanturing881"><code>@alanturing881</code></a>).</li> </ul> <h2>4.28.6</h2> <ul> <li>Fixed Electron version queries (by <a href="https://github.com/spokodev"><code>@spokodev</code></a>).</li> </ul> <h2>4.28.5</h2> <ul> <li>Fixed <code>></code> and <code>>=</code> queries (by <a href="https://github.com/spokodev"><code>@spokodev</code></a>).</li> </ul> <h2>4.28.4</h2> <ul> <li>Fixed <code>SyntaxError</code> regression of 4.28.3.</li> </ul> <h2>4.28.3</h2> <ul> <li>Fixed baseline query case-insensitivity (by <a href="https://github.com/swwind"><code>@swwind</code></a>).</li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/browserslist/browserslist/blob/main/CHANGELOG.md">browserslist's changelog</a>.</em></p> <blockquote> <h2>4.28.8</h2> <ul> <li>Fixed <code>including kaios</code> in baseline queries (by <a href="https://github.com/Jaybhade"><code>@Jaybhade</code></a>).</li> </ul> <h2>4.28.7</h2> <ul> <li>Improved parsing performance.</li> <li>Fixed unbounded memory growth (by <a href="https://github.com/alanturing881"><code>@alanturing881</code></a>).</li> <li>Fixed prototype write issue (by <a href="https://github.com/alanturing881"><code>@alanturing881</code></a>).</li> </ul> <h2>4.28.6</h2> <ul> <li>Fixed Electron version queries (by <a href="https://github.com/spokodev"><code>@spokodev</code></a>).</li> </ul> <h2>4.28.5</h2> <ul> <li>Fixed <code>></code> and <code>>=</code> queries (by <a href="https://github.com/spokodev"><code>@spokodev</code></a>).</li> </ul> <h2>4.28.4</h2> <ul> <li>Fixed <code>SyntaxError</code> regression of 4.28.3.</li> </ul> <h2>4.28.3</h2> <ul> <li>Fixed baseline query case-insensitivity (by <a href="https://github.com/swwind"><code>@swwind</code></a>).</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/browserslist/browserslist/commit/f2f2e6cfb01bb4942941d328737546f4e2ae41ad"><code>f2f2e6c</code></a> Release 4.28.8 version</li> <li><a href="https://github.com/browserslist/browserslist/commit/d0787c88fa29ba895fea51cfe921232c7b5d1377"><code>d0787c8</code></a> Update dependencies</li> <li><a href="https://github.com/browserslist/browserslist/commit/fcf8fa9857b30ccdf801a548f5d09d3c4ff0d43f"><code>fcf8fa9</code></a> Merge pull request <a href="https://redirect.github.com/browserslist/browserslist/issues/939">#939</a> from Jaybhade/fix/baseline-kaios-without-downstream</li> <li><a href="https://github.com/browserslist/browserslist/commit/57ecd64454e9252afdd6a7e76926e13dda48a38c"><code>57ecd64</code></a> fix: support "including kaios" without downstream</li> <li><a href="https://github.com/browserslist/browserslist/commit/093a0f67bb0becda55235d767b134df3197c54a1"><code>093a0f6</code></a> Update EM banner</li> <li><a href="https://github.com/browserslist/browserslist/commit/b637868045806d2fba4c24eb0060e4cc8b1db276"><code>b637868</code></a> Release 4.28.7 version</li> <li><a href="https://github.com/browserslist/browserslist/commit/313f4659b9f985ade89d1d6a54a860371c41cc46"><code>313f465</code></a> Update dependencies</li> <li><a href="https://github.com/browserslist/browserslist/commit/c935c5a206f8b13db8846818bc03643e147dcbdf"><code>c935c5a</code></a> Fix regexp performance</li> <li><a href="https://github.com/browserslist/browserslist/commit/d7e9e653cb53399065943f59f0b3063987b0a008"><code>d7e9e65</code></a> Rewrite structure parsing to make it always fast</li> <li><a href="https://github.com/browserslist/browserslist/commit/ec4a55efd76bdfa506ec7ce4fea1691559e9ca8f"><code>ec4a55e</code></a> Fix import order</li> <li>Additional commits viewable in <a href="https://github.com/browserslist/browserslist/compare/4.28.2...4.28.8">compare view</a></li> </ul> </details> <details> <summary>Maintainer changes</summary> <p>This version was pushed to npm by <a href="https://www.npmjs.com/~GitHub%20Actions">GitHub Actions</a>, a new releaser for browserslist since your current version.</p> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/bytefolk/mem/network/alerts). </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: 勒布朗-詹姆斯 <2986253039@qq.com>
## Tracking record Refs #124 - Consumed revision: [#124 R4](#124 (comment)) - This candidate does not close #124. Merge-SHA evidence and product acceptance remain separate. ## Bounded change The exact diff against main changes one global CODEOWNERS line: ```diff -* @PeterGuy326 @Bindy-lbb +* @PeterGuy326 @Bindy-lbb @waterbro-8 ``` No collaborator role, branch-protection setting, required-review count, administrator bypass, tag ruleset, tag permission, release, or repository setting changes. ## Requirement trace | Requirement / acceptance | Evidence | | --- | --- | | REQ-001; AC-001 | Exact one-line .github/CODEOWNERS diff from base cc727db to head 474fb33. | | REQ-002; AC-002 | Before-state GitHub protection readback confirms strict checks, code-owner review, stale-review dismissal, last-push approval, linear history, admin enforcement, force-push prohibition, and deletion prohibition remain enabled. Exact-head CI is required. | | REQ-003; AC-003 | Diff contains no tag or collaborator configuration; an independent current-head CODEOWNER review remains required. | ## Validation - git diff --check: passed. - git diff --name-only origin/main...HEAD: only .github/CODEOWNERS. - Git author and committer: PeterGuy326 using 47820304+PeterGuy326@users.noreply.github.com. - Sensitive-content scan: no credentials or private data introduced. ## Review and delivery gates This clean candidate supersedes [#132](#132) because that branch has public commits with non-noreply personal metadata. #132 is left unchanged for audit and is not force-pushed or merged. @Bindy-lbb must provide a current-head independent CODEOWNER approval after all required CI is green. The author and last pusher will not self-approve. Normal merge authorization, merge-SHA push/main checks, verification ledger, and product acceptance still apply. Co-authored-by: Bindy <70745012+Bindy-lbb@users.noreply.github.com> Co-authored-by: 勒布朗-詹姆斯 <2986253039@qq.com>
… headers (#161) ## What this changes Implements the security-header split decided for this repository on 2026-09-03: **nginx is the single authority for `X-Content-Type-Options`, `X-Frame-Options` and `Referrer-Policy`, uniformly `no-referrer`, with the proxied path de-duplicated by `proxy_hide_header`; the API keeps `Content-Security-Policy`, `X-XSS-Protection` and `Content-Disposition`.** Closes #135 (the two live proxy defects) and Closes #136 (the ownership question that defect raised). This is the in-repo redo of #144, which came from a fork and is being closed under the fork-policy decision. It is not a cherry-pick of that commit — no commit from it is imported here. ### The two defects, as measured Both were real on `main@1332bf4` and neither is visible by reading the config, which is why the test starts an nginx rather than grepping one. 1. **`/assets/` lost all three headers.** An `add_header` inside a location replaces the inherited set instead of adding to it, and that block has always had `add_header Cache-Control`. Every cached bundle shipped with no `nosniff`, no `X-Frame-Options` and no `Referrer-Policy` at all. 2. **`/v1/` sent two conflicting `Referrer-Policy` values on one response.** The proxy said `same-origin`, the API says `no-referrer`, and nginx's `add_header` appends rather than replaces, so a client received both and the effective policy depended on which one the browser kept. `X-Content-Type-Options` and `X-Frame-Options` were also duplicated (same value twice). ### Why the API keeps sending the three it no longer owns `proxy_hide_header` makes the wire value nginx's, which is what "nginx 独占" requires, without deleting `nosniff`/`DENY`/`no-referrer` from `securityHeadersMiddleware`. A `memd` reached directly — the Helm path exposes the Service, and `docs/DEPLOYMENT.md` only makes the nginx guarantee for the container — keeps its defense in depth. If the intended reading was instead that the Go middleware should stop setting them, that is a one-line change here and it should be said before merge, because the alternative silently weakens the no-proxy deployment. ## Test evidence `scripts/test_nginx_security_headers.sh` renders the shipped template with the same `envsubst` filter and variables the container entrypoint uses, runs a fake upstream that answers exactly like `securityHeadersMiddleware` does, starts nginx against the config, and reads headers off the wire across five surfaces (`/`, `/assets/`, a 404 under `/assets/`, `/v1/`, `/healthz`). | run | result | | --- | --- | | template as shipped on `main` | **11 of 28 assertions fail** — 6 missing across the two `/assets/` surfaces, `same-origin` on `/` and `/healthz`, 3 duplicated on `/v1/` | | this branch | **28 of 28 pass** | | drop the `/assets/` restatement | 3 fail (`/assets/` 200) | | drop `always` from the `/assets/` restatement | 3 fail (`/assets/` 404 only) | | drop `proxy_hide_header` | 3 fail (`/v1/` duplicates) | Each of the three fix sites is therefore individually load-bearing, and the 404 surface earns its place: it is the only one that tests `always`. The harness also refuses to report success on a partial run (the assertion count is pinned), hard-fails when a caller names an `NGINX_BIN` that is not executable, and only reports `SKIP` when no nginx was found at all — so the CI leg cannot go green by measuring nothing. Executed locally against nginx **1.27.4**, the same minor the `web/Dockerfile` pins (`nginxinc/nginx-unprivileged:1.27.4-alpine3.21`). **Measured in CI on the built image, and it did go red there first.** The first run of the new step failed exactly where this paragraph expected the risk to be: `web/Dockerfile:17` ends on `nginxinc/nginx-unprivileged`, whose own build stops at `USER 101`, so `apk add` could not write the package database -- `ERROR: Unable to lock database: Permission denied`, `exit code: 99`. Commit `1c917f96` installs the four tools in a throwaway child image that returns to uid 101 afterwards, so the harness still runs unprivileged, as the shipped container does. On that head `Deployment profiles` is green and its job log carries `all 28 security-header assertions passed`, so the leg executed the contract against the nginx that ships rather than printing `SKIP`. The harness content measured above is unchanged by that commit; it touches only the workflow step. ## Not in scope here, and worth a decision Nothing in this repository sets a `Content-Security-Policy` for the SPA itself — `default-src 'none'` is an API-only value and would break the web app if applied to it. The decided split covers the three shared headers and leaves HTML/SPA CSP unowned. This PR deliberately does not invent one. ## Links and state - `Refs` the decided split; `Closes #135` / `Closes #136` on merge. - No Go code changed, so the existing `security_headers_test.go` and `content_*` tests are unaffected. - `Web` is red on this head and identically red on `main` itself (`Audit dependencies`, `browserslist <=4.28.6`, GHSA-73wf-gq98-2v4g). That is a pre-existing repository condition rather than something this branch introduced, and the queued fix is #159; the readback is on #138. - Opening this PR is not a claim that it should be merged. Independent review is the reviewers'; I have not requested or recorded one. --------- Co-authored-by: waterbro-8 <318569545+waterbro-8@users.noreply.github.com>
## Tracking record Refs #133 - Consumed revision: [#133 R1](#133 (comment)) - This PR does not close the Issue. Product acceptance remains a separate step after merge evidence. ## Why A concurrent cold-cache install on Windows can surface mkdir contention as EPERM or EACCES rather than EEXIST. The installer previously treated only EEXIST as retryable. The original remediation candidate [#134](#134) also left a P1 retry path: an EEXIST to ENOENT or stale-rename race could retry synchronously before its deadline or abort-aware delay. This is a clean successor to #134. That older public branch is left intact for audit; no history is rewritten or force-pushed. ## Scope - Classify EEXIST as lock contention on every platform and EPERM or EACCES as potential contention only on win32. - Prove a lock can be inspected before retrying a Windows permission-shaped contention error; unproven permission failures still fail closed. - Route every failed acquisition, including stale recovery and lock-disappearance races, through the existing deadline and abort-aware poll. - Add deterministic regression coverage and the Unreleased changelog entry. No lock primitive, per-asset ownership model, stale or orphan threshold, dependency, public API, tag, npm publication, or release behavior changes. ## Requirement trace | Requirement / acceptance | Implementation | Evidence | | --- | --- | --- | | REQ-001; AC-001, AC-002 | npm/install.js error classifier and acquireAssetLock | Host-independent classifier table and real-lock simulated Windows EPERM acquisition test. | | REQ-002; AC-003 | npm/install.js lock inspection path | Persistent no-lock EPERM and inspection EACCES tests reject promptly. | | REQ-003; AC-004 | npm/install.js platform guard | Linux and Darwin keep EPERM or EACCES fatal; exact-head Windows CI remains required. | | REQ-004; AC-001, AC-004 | injectable osPlatform plus npm/install.test.js | win32 branch is exercised off Windows; hosted node24-windows job is required before review. | | AC-005 | CHANGELOG.md | Unreleased user-visible fix note. | ## Failure evidence and regression proof At base cc727db, a deterministic pre-require fs injection of EEXIST followed by lstat ENOENT produced two immediate lock mkdir attempts and an EPERM sentinel: the retry bypassed its zero wait deadline. This candidate makes the same path return the expected timeout after one attempt. A separate stale rename ENOENT race has the same bounded behavior. ## Validation Local macOS, Node 24: | Command | Observed result | | --- | --- | | PATH=/Users/huyz/.nvm/versions/node/v24.14.1/bin:$PATH npm test in npm/ | 41 passed, 0 failed, 1 Windows-only shim skipped as expected on macOS | | node --test npm/install.test.js | 30 passed, 0 failed | | node --check install.js; node --check mem-mcp; node --check platforms.js | passed | | npm pack --dry-run --ignore-scripts | passed; six expected package files only | | git diff --check | passed | | focused added-diff sensitive-pattern scan | no matches | Independent preflight replayed the focused and full Node 24 suite, plus the full Node 18 suite: 41 passed, 0 failed, 1 expected Windows-only skip in each full run. It found no P0 or P1 and recorded PREFLIGHT PASS for this code candidate. ## Review and delivery gates - Exact head required CI, especially npm wrapper compatibility (node24-windows), must be green. - @Bindy-lbb must provide an independent current-head CODEOWNER approval. The author and last pusher will not self-approve. - Normal merge authorization, merge-SHA push/main verification, verification ledger, and product acceptance remain required. ## Security, compatibility, and release boundary The retry set is deliberately narrow. On Windows, EPERM or EACCES is retried only after a lock can be inspected; otherwise the original error is surfaced. Non-Windows behavior remains fail-closed. No credentials, dependencies, or public-history changes are introduced. v0.1.1 was already published from main. This candidate may only enter a later, separately authorized release; it does not authorize a tag move, npm publish, GitHub Release, merge, or Issue closure. Co-authored-by: waterbro-8 <318569545+waterbro-8@users.noreply.github.com>
Queued for protected squash merge after independent Code Owner approval and green security checks.
## Requirement / goal Refs #139 (CI baseline only; this PR does not expand the checkpoint bug scope). Restore the current `mem` Web audit gate by refreshing the lockfile entries with published fixes. ## Scope - Refresh only `web/package-lock.json`. - Resolve the current main Web audit findings for js-yaml, Vitest/@vitest/mocker, and postcss-selector-parser. - No application code, server behavior, transcript format, or checkpoint implementation changes. ## Validation ledger - PASS — `npm ci` - PASS — `npm run audit` (production and high-severity development gates) - PASS — `npm run lint` - PASS — `npm run typecheck` - PASS — `npm run build` - PASS — `git diff --check` ## Known limitations - This is a CI/security-baseline prerequisite for clean current-main PR validation, not the #139 product fix and not an issue-close claim. - The lockfile refresh is intentionally separate from [#191](#191); #191 should be rebased or retargeted after this baseline lands.
) ## What this changes `mcpName` becomes **`io.github.bytefolk/mem-mcp`** in `npm/server.json` and `npm/package.json`. This implements the registry half of the 2026-09-03 decision that G5 does not wait on an npm scope migration. The official MCP Registry derives an entry's namespace from the **repository owner**. The value on `main` still names `fullstack-ai-infra`, which this repository no longer is, so a submission carrying it either points into a namespace we do not control or is rejected by namespace validation. That single stale string is why the registry listing never appeared — reading `search=io.github.fullstack-ai-infra` and `search=bytefolk` against the public registry API both return `count: 0`, so there is no prior record to migrate over. ## What is deliberately not changed | | value | why it stays | | --- | --- | --- | | npm package name | `@fullstack-ai-infra/mem-mcp` | The decision keeps the published scope. A registry identifier and an npm package identifier are different namespaces; moving the package would break every existing `"args": ["-y", "@fullstack-ai-infra/mem-mcp"]` client config and every cached install for no registry-side gain. | | installer cache directory | `…/fullstack-ai-infra/mem-mcp` | Renaming it discards working caches to change a folder name. | | version | `0.1.1` | `scripts/validate_release_version.sh:39` pins `npm/server.json`'s version to the tag, so the bump belongs to the release commit, not here. | The resulting shape — npm scope `@fullstack-ai-infra`, registry namespace `io.github.bytefolk` — is intentional and is what the new test encodes, so it does not read as a half-finished migration. ## The guard The defect was a stale string in a manifest, and a rename is precisely the event that makes a manifest stale, so `npm/registry-identity.test.js` now asserts the identifier against the repository coordinate `npm/install.js` already downloads from. It derives the expected namespace rather than hardcoding `bytefolk`, so a future rename moves the assertion instead of breaking it. | run | result | | --- | --- | | this branch | 3/3 pass | | `mcpName` left on `fullstack-ai-infra` (the shipped state) | 2 of 3 fail | | repository coordinate renamed, identifier not followed | 1 of 3 fails | | full `npm test` | 38 tests, 37 pass, 1 pre-existing platform skip | | same on `main@1332bf4` | 35 tests, 34 pass, 1 skip | Added to the `test` script's file list, so it runs in the `npm-wrapper` CI job rather than only when named directly. ## Two things to know before reviewing - **`npm run test:tarball` fails on this branch and identically on `main`.** It is an `npm install --offline` of the locally packed tarball against this host's npm cache, not something this change touched. CI invokes it as `npx --yes npm@12.0.2 run test:tarball`, which this host cannot reproduce, so treat that leg as CI-covered only. - **#153 now contradicts this PR.** That issue asks to migrate the package to `@bytefolk/mem-mcp`; the decision is to keep the scope. I linked with `Refs #153`, not `Closes`, because only the registry half is done here. #153 should be rewritten, or the next person to pick it up will move the scope and undo the part that was never in question. ## Not in this PR Running `mcp-publisher` and the OAuth / organization verification are assigned to @PeterGuy326, and the registry record is created by that submission, not by merging this. `README.md:11` also still points its Smithery badge at `@fullstack-ai-infra/mem-mcp`; that slug needs verifying against what Smithery actually resolves before it is edited, so it is left alone here rather than repointed to something possibly equally wrong. Merging this PR is not a claim that it is merge-ready, and no review has been requested or recorded. Co-authored-by: waterbro-8 <318569545+waterbro-8@users.noreply.github.com> Co-authored-by: 修雨 <47820304+PeterGuy326@users.noreply.github.com>
…/web (#160) Bumps [postcss-selector-parser](https://github.com/postcss/postcss-selector-parser) from 6.1.2 to 6.1.4. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/postcss/postcss-selector-parser/releases">postcss-selector-parser's releases</a>.</em></p> <blockquote> <h2>6.1.4</h2> <ul> <li>fix: tolerate non-node children when serializing selectors</li> </ul> <h2>6.1.3</h2> <ul> <li>Fix <a href="https://github.com/advisories/GHSA-w9m9-85wc-3x92">CVE-2026-9358</a> (NVD) / SNYK-JS-POSTCSSSELECTORPARSER-16873882 via backport of (<a href="https://redirect.github.com/postcss/postcss-selector-parser/pull/316">#316</a> by <a href="https://github.com/MoOx"><code>@MoOx</code></a>)</li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/postcss/postcss-selector-parser/blob/main/CHANGELOG.md">postcss-selector-parser's changelog</a>.</em></p> <blockquote> <h1>Changelog of <code>postcss-selector-parser</code></h1> <h2>7.1.5 - 2026-08-07</h2> <ul> <li>fix: don't treat a non-prefix token before <code>|</code> as a namespace (<a href="https://redirect.github.com/postcss/postcss-selector-parser/pull/324">#324</a> by <a href="https://github.com/spokodev"><code>@spokodev</code></a>)</li> <li>fix: preserve whitespace before a <code>*</code> namespace in attribute selectors (<a href="https://redirect.github.com/postcss/postcss-selector-parser/pull/325">#325</a> by <a href="https://github.com/spokodev"><code>@spokodev</code></a>)</li> <li>fix: TypeError on unclosed <code>[</code>, <code>(</code> and trailing <code>|</code> (<a href="https://redirect.github.com/postcss/postcss-selector-parser/pull/330">#330</a> by <a href="https://github.com/theRizwan"><code>@theRizwan</code></a>)</li> </ul> <h2>7.1.4 - 2026-06-11</h2> <ul> <li>fix: tolerate non-node children when serializing selectors</li> </ul> <h2>7.1.3 - 2026-06-11</h2> <ul> <li>Improve fix CVE-2026-9358 (NVD) / SNYK-JS-POSTCSSSELECTORPARSER-16873882 (clone/walk)</li> </ul> <h2>7.1.2 - 2026-06-09</h2> <ul> <li>Fix <a href="https://github.com/advisories/GHSA-w9m9-85wc-3x92">CVE-2026-9358</a> (NVD) / SNYK-JS-POSTCSSSELECTORPARSER-16873882 (<a href="https://redirect.github.com/postcss/postcss-selector-parser/pull/316">#316</a> by <a href="https://github.com/MoOx"><code>@MoOx</code></a>)</li> </ul> <h2>7.1.1</h2> <ul> <li>perf: replace startsWith with strict equality (<a href="https://redirect.github.com/postcss/postcss-selector-parser/issues/308">#308</a>)</li> <li>fix(types): add walkUniversal declaration (<a href="https://redirect.github.com/postcss/postcss-selector-parser/issues/311">#311</a>)</li> </ul> <h2>7.1.0</h2> <ul> <li>feat: insert(Before|After) support multiple new node</li> </ul> <h2>7.0.0</h2> <ul> <li>Feat: make insertions during iteration safe (major)</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/postcss/postcss-selector-parser/commit/4a7e4e3685db8ab8e52e51ecdbe8162a8568f70c"><code>4a7e4e3</code></a> 7.1.4</li> <li><a href="https://github.com/postcss/postcss-selector-parser/commit/e2021c523d5ef1bf27836aef3bd724a28ba7894f"><code>e2021c5</code></a> fix: tolerate non-node children when serializing selectors</li> <li><a href="https://github.com/postcss/postcss-selector-parser/commit/7893b741fa87d0401e39c3a7f00d89cf7408ad32"><code>7893b74</code></a> 7.1.3</li> <li><a href="https://github.com/postcss/postcss-selector-parser/commit/5bc698cef66f8abd12610dc623e5d67cbc0f869d"><code>5bc698c</code></a> Improve fix CVE-2026-9358 (NVD) / SNYK-JS-POSTCSSSELECTORPARSER-16873882 (clo...</li> <li><a href="https://github.com/postcss/postcss-selector-parser/commit/db3232710d7270b34e50b4ffae493ac19204f570"><code>db32327</code></a> run oxfmt</li> <li><a href="https://github.com/postcss/postcss-selector-parser/commit/16e2581b40894504cf2b979fc0ebf7d0b2f39366"><code>16e2581</code></a> simplify deps (<a href="https://redirect.github.com/postcss/postcss-selector-parser/issues/319">#319</a>)</li> <li><a href="https://github.com/postcss/postcss-selector-parser/commit/b185e2057871669f9c571ad82e4350799e0a2329"><code>b185e20</code></a> Add description in package.json + full repo url</li> <li><a href="https://github.com/postcss/postcss-selector-parser/commit/de415f19aac008f0e731590222f3a963193be05c"><code>de415f1</code></a> Add Tidelift security notice</li> <li><a href="https://github.com/postcss/postcss-selector-parser/commit/c4f2c8c04a8107e4e401f257ef00592b59633774"><code>c4f2c8c</code></a> CI: make Node 14 test job lockfile-v3 compatible (<a href="https://redirect.github.com/postcss/postcss-selector-parser/issues/318">#318</a>)</li> <li><a href="https://github.com/postcss/postcss-selector-parser/commit/4e93663bfe861f9fc3173db603c8fadb70f8090a"><code>4e93663</code></a> Fix test run on node < 20</li> <li>Additional commits viewable in <a href="https://github.com/postcss/postcss-selector-parser/compare/v6.1.2...6.1.4">compare view</a></li> </ul> </details> <details> <summary>Maintainer changes</summary> <p>This version was pushed to npm by <a href="https://www.npmjs.com/~moox">moox</a>, a new releaser for postcss-selector-parser since your current version.</p> </details> <br /> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: 勒布朗-詹姆斯 <2986253039@qq.com> Co-authored-by: 修雨 <47820304+PeterGuy326@users.noreply.github.com>
…165) Refs #112 ## Summary A configured URL that carries credentials in a shape `url.Parse` does not report as **userinfo** reaches output today. This adds one shared gate that redacts such a value when it can prove it is a transport URL, and **withholds the value whole** when it cannot, and wires it into all three egresses R3 names: the API client, `memd`'s log lines, and `mem doctor`. The adjudicated direction this implements is recorded on #112 as R3 (comment 5536659086): gate on *"parses as a recognized transport scheme with userinfo redacted, otherwise withhold the whole value"*. ## Scope: all three named egresses R3 names three egresses — doctor, apiclient, `memd`'s log line. All three are covered here. | egress | on `main` at the base | covered here | | --- | --- | --- | | apiclient — request construction | leaks | gated | | apiclient — all 4 `http.Client.Do` sites | leaks, ungated entirely | gated, one test case per site | | apiclient — `newRequest` on the workspace-transfer path | leaks | gated (arrived with #164's `workspace_transfer.go`) | | `memd` startup log line | leaks (`User != nil` gate) | gated | | `memd` fatal log line | leaks via a third-party error | gated | | `mem doctor` (text + JSON) | not present | gated through the same package | ### How doctor got onto this branch `mem doctor` is not on `main`; it only existed on #164 (which sits on #131's original doctor commit). Because #131 was closed as superseded by #164, doctor had exactly one carrier, so the surviving branch had to absorb it before #164 could be closed. Rather than re-author it, this branch **merges** the work: ``` c9e0e63 docs: correct doctor's stated secret guarantee (this change) d30f1ff fix(cli): route mem doctor's URL reporting through the shared gate (this change) ad4e78f Merge origin/main d7f2dcb Merge #164 (mem doctor) into the credential-url-gate branch b229537 fix(client,memd): withhold URLs whose credentials cannot be attributed fffcd4c fix(cli): redact malformed URLs and request build errors ← #164, author PeterGuy326 46499b2 feat(cli): add mem doctor and first-run guidance ← #131, author waterbro-8 ``` Both earlier commits are **ancestors** of this head, so #164's and #131's authorship is preserved on the merge rather than claimed as mine. #164's unrelated per-probe `--timeout` fix and its `workspace_transfer.go` coverage came across with the merge and are kept. What `d30f1ff` itself does is replace doctor's two local string-level helpers with calls into `internal/redact`, so there is one policy rather than three: ```go func redactURL(raw string) string { return redact.URL(raw, redact.APIURLs) } func sanitizeProbeError(err error) string { return redact.TransportError(err, redact.APIURLs) } ``` `c9e0e63` is prose only. It corrects three statements — in `CHANGELOG.md`, `docs/DEPLOYMENT.md` and a comment in `cmds_doctor.go` — that asserted the doctor report contains **no secret value**. That was never true of the query-parameter shape described under Known gap, measured at 3 sentinel occurrences per output format on this head. The non-goal stands; the promise was the thing that was wrong, so the docs now name the residual instead of denying it. ## The shape, and why the previous gate missed it ``` url.Parse("admin:pw@host") → Scheme="admin" Opaque="pw@host" User=nil ``` A gate written as `if parsed.User == nil { return raw }` therefore echoes the credential verbatim — not as a corner case, but as the normal path for any value whose scheme happens to contain a colon. The gate also refuses to scrub error *text*, because that cannot be made tight: `url.Error` renders with `%q`, so a `"` inside a password arrives escaped and a scanner that pairs quotes mis-pairs, replaces nothing, and leaves its cursor inside the URL. Withholding is chosen over partial trimming for the same reason: a delimiter inside a credential splits the message into pieces that no longer look like a URL, and the piece without the `@` is exactly the half that leaked. `memd`'s fatal line is included because `queue.NewClient` wraps asynq's parse error, which embeds the whole DSN: ``` queue: parse redis url: asynq: could not parse redis uri: parse "redis://:PASS@ho st:6379/0": invalid character " " in host name ``` slog renders an error value as its text, so that reaches the log unmodified. ## Known gap, stated rather than smoothed over The gate proves the absence of **userinfo**, not of every credential. A secret supplied as a query parameter (`redis://host:6379/?password=x`) parses as a clean URL with `User == nil` and **is still echoed**. This is the adjudicated scope, not an oversight, and closing it is a separate decision. It is pinned by a named characterization test (`TestTextKnownGapQueryParameterCredentialsAreEchoed`) that fails if someone closes the gap without updating the expectation, so the residual cannot become folklore. Withholding also has a real diagnosability cost, accepted by design: the reason a request failed is still reported, the host is not. ``` Error: Get [withheld]: unsupported protocol scheme "admin" ``` ## Validation ledger Evidence level claimed: **E3 — independently reproduced**. Not E4: I am the author, and E4 requires a non-author to verify the acceptance criteria end to end. Environment: Linux x64, Go 1.25.0, exact tree `9fa9c14de074b4ddb5320d4f83803f1657918b34` — `HEAD^{tree}` of the current head `c9e0e63`, read back from `GET /repos/bytefolk/mem/commits/c9e0e63…` and equal to it byte-for-byte, so the tree measured here and the tree on the PR are the same object. (This head was pushed through the Git Data API because `github.com:443` was down on this box; the local commit sha differs from the remote one, the tree does not.) | Check | Result | | --- | --- | | `go build ./...` | pass | | `go vet ./...` | pass | | `gofmt -l .` | no output | | `go test -count=1 ./...` | 32 packages ok, 0 FAIL | | `cmd/mem` (includes 16 `mem doctor` tests) | 102 tests, 0 fail | | `internal/redact` | 30 tests, 0 fail | | `internal/apiclient` | 45 tests, 0 fail | | `cmd/memd` | 15 tests, 0 fail | | `git merge-base --is-ancestor origin/main HEAD` | yes (main not silently reverted) | | CI on this head | **15/15 check names `success`** on `c9e0e63` (`run_attempt` 1), including `Go` and `PostgreSQL integration`; also 15/15 on the immediately preceding `d30f1ff` | ### `mem doctor` end-to-end, measured on built binaries Seven malformed credential URL shapes, each run through `mem doctor --server <shape> --timeout 1s` in **both** `text` and `json`, counting occurrences of a sentinel password in everything the process wrote: | # | shape | #164 head `fffcd4c` | this head `c9e0e63` | | --- | --- | --- | --- | | 1 | `http://admin:PW@127.0.0.1:1` | 0 | 0 | | 2 | `http://admin:PW@127.0.0.1:%zz` | 0 | 0 | | 3 | `http://admin:PW@ho st.example.com` | 0 | 0 | | 4 | `http://admin:PW x@127.0.0.1:1` | 0 | 0 | | 5 | `http://admin:PW@%` | 0 | 0 | | 6 | `http://admin:PW@mem.internal:99999999` | 0 | 0 | | 7 | `admin:PW@mem.internal:8787` (no scheme) | **6** | **0** | Shape 7 is the `url.Parse` → `User=nil` case from the section above: #164 prints the configured URL three times (`server`, `detail`, `hint`) in each of the two formats, so 6 occurrences is one leak per field. **A zero from a binary that has no `doctor` command means nothing.** This table was first produced against a build of `b229537` and came back 0/0/0/0/0/0/0, which looked like a pass — the actual output was `Error: unknown command "doctor" for "mem"`, because that head had no doctor at all. The harness now counts `unknown command` alongside `unknown flag` and every row above was taken with both counters at 0. ### Mutation controls Run against a copy, with the mutation confirmed present in the source before the suite is trusted: 1. Reverting the gate to the pre-fix `User != nil` form turns **10 named cases red across 3 packages** (`internal/redact`, `cmd/memd`, `cmd/mem`). 2. Removing the gate at **one** apiclient `Do` site turns red **exactly that site's** test case and leaves the other three green. The four cases map one-to-one onto the four sites, so a regression at a single site cannot hide. Control 2 was found by this method — an earlier version of this port left one site raw and the table caught it. 3. Putting **#164's original `redactURL` / `sanitizeProbeError` back** into this tree — i.e. merging #164 and *not* rewiring doctor — fails **exactly one test**, `TestDoctorSchemelessServerURLDoesNotLeakCredentials`, and its built binary leaks 2 sentinel occurrences on shape 7. Before that test was added, the same mutation failed **zero** tests. So the merge on its own was unprotected, and the one new test is what closes that. ### Two pre-existing assertions were relaxed — named, because one is not mine The gate withholds a value it cannot prove is a transport URL, where #164's local helper echoed a partially cleaned one. Two assertions demanded the echo shape specifically, so they were widened to accept **redact *or* withhold**: | location | test | author of the assertion as written | | --- | --- | --- | | `cmds_doctor_test.go:418` | `TestRedactURLStripsUserinfo` | waterbro-8 (#131) | | `cmds_doctor_test.go:456` | `TestDoctorMalformedServerURLDoesNotLeakCredentials` | **PeterGuy326 (#164)** | Both keep their original first clause — the secret must not appear, and a cleaned URL must still carry `REDACTED@<host>`. Only the *form* of an acceptable answer widened. Concretely at `:418`, `strings.Contains(got, secret)` still fails the test, and the `REDACTED@mem.internal:8787` check two lines above it is untouched. **No assertion was deleted, and the count went up, not down**: #164's 15 doctor tests are all present on this head (0 dropped), plus `TestRedactURLStripsUserinfo` and the new `TestDoctorSchemelessServerURLDoesNotLeakCredentials` = **16**. The way to check this claim is mutation control 3 above: if the widening had quietly weakened coverage, restoring #164's scrubber would have gone green, and instead it fails a test. Anyone who considers the withhold form unacceptable for `:456` should say so on #164's thread rather than assume I settled it unilaterally — I changed an assertion another author wrote to pass my gate. ## What I did not verify - The leak table was rebuilt and re-run against `c9e0e63` after the docs commit; that commit is prose and comments only, and the result is unchanged (0 on all seven shapes). Earlier heads `d30f1ff` and `b229537` each had 15/15 CI at the time they were written. - **There is no prior CI baseline for the doctor half to compare against.** #164's head `fffcd4c` has 0 `check-runs` and no workflow run has ever been recorded for it, so doctor has never been green in CI anywhere — including here, where it is now inside the `Go` job for the first time. That is a gain, not a regression, but it does mean no one has seen this code pass CI before. - Nothing was exercised on Windows or macOS. All results are Linux x64. - `memd` was **not** driven end-to-end to its fatal redis path. Reaching it requires a reachable PostgreSQL (the queue client is constructed after `db Open`), and the only local server on 5432 is an unrelated instance whose credentials I do not have — my attempt failed at `db open: ... failed SASL auth` before touching the queue. That egress is therefore evidenced by executing the gate on the asynq error string **measured from the real library in this tree**, not by a live `memd` run. - No claim is made about `#112`'s exit-code contract, R2/R3 acceptance, or #131/#164 merge readiness. ## Non-goals - No change to query-string credential handling (see Known gap). - No change to `#164`'s or `#131`'s branches; nothing here is pushed to anybody else's ref. #164 is pulled *into* this branch by merge, which is why #164 can be closed without losing its work. - No re-adjudication of R3. Doctor's `--timeout` behaviour, its check set and its JSON schema are #164's, unchanged except where they called the old local helpers. This PR stays `Refs` on #112 rather than `Closes`, because merging it would not by itself settle #112's acceptance — that needs a reviewer's decision, not just a diff landing. **Review strength of this PR, stated plainly:** 15/15 checks pass on `c9e0e63`, and I am the author of `b229537`, `d30f1ff` and `c9e0e63` — automated checks and my own sign-off are not a review. What this PR is missing is exactly one independent human review; nothing else blocks it (`mergeable=true`, no conflict with `main`, which is an ancestor of this head). It needs one human approval, and I am not that reviewer — on the doctor half especially, since I edited an assertion PeterGuy326 wrote. --------- Co-authored-by: waterbro-8 <waterbro-8@users.noreply.github.com> Co-authored-by: PeterGuy326 <47820304+PeterGuy326@users.noreply.github.com> Co-authored-by: waterbro-8 <318569545+waterbro-8@users.noreply.github.com>
### Not a review vote, and not an acceptance I am the author of this branch, so under this org's `require_code_owner` + `require_last_push_approval` configuration my own ticket cannot be the one that clears it. Nothing here asks for a merge, a close, a label, or a tag. The commitment is only: here is a change, here is what I measured. Supersedes nothing by itself: **#156 is a separate, still-valid Dependabot PR.** See *Sequencing* below. ### What changes Two files, +39/−39: - `worker/pyproject.toml:31` — `"pypdf>=4.0"` → `"pypdf>=6.18.0"` - `worker/uv.lock` — `pypdf 6.15.0 → 6.18.0`, nothing else moves That is the whole diff. No test, no docs, no CI file, no `CHANGELOG.md` entry: `grep -i 'pypdf\|numpy\|torch\|dependabot' CHANGELOG.md` on `main` returns **zero** dependency-bump entries across its 381 lines, and #156 is 2 files too, so an entry here would be inventing a convention. ### Why the floor is written `>=6.18.0` and not `>=6.16.1` Three open Dependabot alerts name `pypdf` in this lock — `#71` (`GHSA-jp53-mhqp-8xcg`, `< 6.16.0`), `#72` (`GHSA-763m-79hh-57f2`, `< 6.16.1`), `#73` (`GHSA-23w6-3w8w-8484`, `< 6.16.1`). This satisfies all three, the same as #156, once it is on the default branch. It additionally takes two upstream releases that **have no advisory**, so no alert will ever schedule them: - **6.17.0** (2026-09-04) — `Security (SEC): Limit value for Roman numerals (#4047)` - **6.18.0** (2026-09-07) — `Security (SEC): Limit allowed length of indirect object tokens (#4055)` Re-measured for this PR: `GET /advisories?affects=pypdf` → **43** entries, all `type: reviewed`, and the newest `first_patched_version` anywhere in that set is **6.16.1**. Both new entries are the same hardening class as the three above (bound an unbounded parser input), and the surface is the untrusted one: `worker/mem_worker/processors/pdf.py:79` runs `PdfReader(BytesIO(file.data))` on **user-uploaded** files. Writing the floor at 6.18.0 rather than letting the lock alone carry it is the part that survives a from-scratch resolve. Measured: **uv resolves to the newest release satisfying a floor, not to the floor** — `>=6.16.1` re-resolved today lands on 6.18.0, and after the next release it would land past it, in a manifest whose stated requirement was never 6.18.0. ### Evidence All of it executed on a tarball of `main @ 2986fe3` whose tree was proved equal to the remote (`.commit.tree.sha` `f447ca554377e85ba26090d59882b8d4f2b78731` == `git init && git add -A && git write-tree`), with the tool CI pins — uv `0.9.27` (`ci.yml:185-187`) — in a sanitized env (no mirror/proxy variables; `uv lock` through a mirror-configured uv rewrites thousands of URL lines and its "lock is stale" verdict is then worthless). | # | check | result | | --- | --- | --- | | 1 | `uv lock` on the **untouched** tree | **0 diff lines** vs committed `worker/uv.lock` — the pin is reproducible, so everything below is about the resolve, not a stale tool | | 2 | `uv lock` after only the constraint edit | `Updated pypdf v6.15.0 -> v6.18.0`, 76 lock lines | | 3 | name/version pairs, both locks | 85 packages each, **exactly one** difference: `pypdf 6.15.0 → 6.18.0` | | 4 | `uv lock --locked` | `rc=0` — so the Worker leg's `uv sync --frozen` (`ci.yml:193`, `UV_FROZEN: "1"` at `:170`) accepts it | | 5 | dist hashes vs the registry | sdist `ae58b7d93c22c169ffb02c3b06321c45c4f223b4916536568adb57d789d95d01`, wheel `05b762b77bcb9dcb4a7c91fcf5dded585b25bee7269ab3d3001d7c55fa1b324b` — byte-identical to `pypi.org/pypi/pypdf/json` | | 6 | the repo's own fixture (`test_processor_logic.py:419`) extracted at 6.15.0 / 6.16.1 / 6.18.0 on **Python 3.11** (`ci.yml:182`) | identical `page_count`, identical `sha256(extracted_text)` (`46e7c072b2684841…`, 214 chars), `"1800 RMB" in text` true on all three, malformed input raises the same `PdfStreamError` on all three | | 7 | 6.18.0's only behavioural change (`DEP: Rework configuration value handling (#4044)`) | `grep` over the whole tree for `overwrite_configuration` / `apply_configuration` / `disable_legacy_handling` / `pypdf.constants` → **0 hits**; `pypdf` appears in only 3 files (`worker/pyproject.toml`, `worker/mem_worker/processors/pdf.py`, `scripts/seed_demo_data.sh`) | Checks 1–4 and 7 are the ones CI cannot shortcut; 6 is the one that says "the worker's PDF path behaves the same", and 4 is the one that says "this lock is self-consistent". The Worker test leg on the exact head remains the real proof of the full pipeline (`test_processor_logic.py:457`) — **that runs in CI, I did not run it here**; the local venv has none of the Worker's own dependencies installed. About the diff size: of the 76 changed lock lines, **8 are pypdf** (specifier, version, sdist, wheel — each on both sides). The other 68 are uv's marker renormalisation: the `python_full_version >= '3.15' and sys_platform == 'darwin'` fork marker hopping between `torch 2.13.0` and `2.13.0+cpu` (likewise `torchvision 0.28.0` / `+cpu`), `python_full_version` narrowing dropping off `numpy` / `scipy` / `tifffile`, and the `resolution-markers` list reordering. That is not avoidable churn I chose: **a plain `uv lock` on either side of a pin costs 0 lines, but any resolve that moves pypdf pays them** — #156's own `+53/−53` is the same shape. No other package's *version* changes. ### Process: this PR is ahead of its issue's readiness gate `AGENTS.md` rule 2 says not to implement a material change until its issue has acceptance criteria and `status:ready`. Refs #187, which I filed with the AC list and reproduction steps for exactly this; it is `status:needs-triage`, and `status:ready` is a maintainer's label, not mine to set. So this is a **draft**, and undrafting it is the step that should follow that label rather than precede it. If triage would rather the change go in behind #156, #187 can simply wait. ### Sequencing with #156 Both branches touch the same two files, so they will conflict with each other, not with `main`. - If **#156 merges first**: rebase this onto the new `main` — the manifest line is a one-token edit and the lock is one `uv lock` with the pinned tool. I offered to do that; it is not something to do unasked. - If **this merges first**: #156's diff is a strict subset of this one and its three alerts are dismissed by this branch instead. **I am not asking for #156 to be closed** — it has an in-force `APPROVED` from `PeterGuy326` on its current head and I am not in a position to spend someone else's ticket. That call, and the release-cadence call about whether 6.17.0/6.18.0 belong in this repo's Worker at all, is the owner's. ### What I did not do No review submitted, no vote, no merge, no close, no label change on anything except the new issue's own labels, no ref moved on #156, no `Update branch` clicked anywhere, no `CHANGELOG.md` edit, no tag, no publish. Co-authored-by: waterbro-8 <318569545+waterbro-8@users.noreply.github.com> Co-authored-by: 修雨 <47820304+PeterGuy326@users.noreply.github.com>
…rver (#158) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.82.1 to 1.83.2. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/grpc/grpc-go/releases">google.golang.org/grpc's releases</a>.</em></p> <blockquote> <h2>Release 1.83.2</h2> <h1>Security</h1> <ul> <li>server: Reject requests missing both <code>:authority</code> and <code>Host</code> headers with HTTP 400 and status <code>Internal</code>. (<a href="https://redirect.github.com/grpc/grpc-go/pull/9365">grpc/grpc-go#9365</a>) <ul> <li>Special Thanks: <a href="https://github.com/winklemad"><code>@winklemad</code></a></li> </ul> </li> </ul> <h2>Release 1.83.1</h2> <h1>Security</h1> <ul> <li>xds/rbac: Fix a bug where nested <code>Principal</code> or <code>Permission</code> rules with <code>:scheme</code> or <code>grpc-</code> prefixed header matchers were not rejected, which could cause DENY rules to fail open. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9258">#9258</a>) <ul> <li>Special Thanks: <a href="https://github.com/nvxbug"><code>@nvxbug</code></a></li> </ul> </li> <li>xds/rbac: Fix a bug where the <code>host</code> header matcher was not being replaced with <code>:authority</code> in nested <code>Principal</code> or <code>Permission</code> rules. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9258">#9258</a>) <ul> <li>Special Thanks: <a href="https://github.com/nvxbug"><code>@nvxbug</code></a></li> </ul> </li> <li>xds/rbac: Fix a bug where a header matcher whose name was not lowercase, such as <code>X-Role</code>, matched no header, which could cause DENY rules to fail open. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9332">#9332</a>) <ul> <li>Special Thanks: <a href="https://github.com/alimony"><code>@alimony</code></a></li> </ul> </li> <li>xds/rbac: Fix a bug where a <code>:scheme</code> or <code>grpc-</code> prefixed header matcher was accepted when its name was not lowercase. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9332">#9332</a>) <ul> <li>Special Thanks: <a href="https://github.com/alimony"><code>@alimony</code></a></li> </ul> </li> <li>xds/rbac: Fix a bug where a <code>Host</code> header matcher was not replaced with <code>:authority</code>. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9332">#9332</a>) <ul> <li>Special Thanks: <a href="https://github.com/alimony"><code>@alimony</code></a></li> </ul> </li> </ul> <h1>Performance</h1> <ul> <li>transport: Restrict memory overhead of buffering small data frames. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9331">#9331</a>)</li> </ul> <h2>Release 1.83.0</h2> <h1>Security</h1> <ul> <li>server: Stop reading from connections when flooded by HTTP/2 frames to mitigate resource exhaustion. The default value for this limit is 100 frames, excluding DATA and HEADERS, and may be changed by setting environment variable <code>GRPC_GO_EXPERIMENTAL_CONTROL_BUFFER_THROTTLE_LIMIT</code>.</li> <li>xds/rbac: Support <code>Metadata</code> and <code>RequestedServerName</code> permissions matcher fields. If present in a DENY rule, previously these would be ignored and fail-open.</li> <li>xds/rbac: Fix panic when parsing unsupported fields in <code>NotRule</code>/<code>NotId</code> permissions.</li> <li>xds/rbac: Support the deprecated <code>source_ip</code> principal identifier by treating it as equivalent to <code>direct_remote_ip</code>.</li> <li>xds: Fix panic when parsing route header matchers configured with empty <code>exact_match</code>, <code>prefix_match</code>, or <code>suffix_match</code> strings. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9223">#9223</a>)</li> </ul> <h1>New Features</h1> <ul> <li>xds/googlec2p: Enable DirectPath over Interconnect support for on-premises clients via the <code>force-xds</code> target URI query parameter. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9133">#9133</a>)</li> <li>xds: Enable xDS configuration to control which fields get propagated from ORCA backend metric reports to LRS load reports. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9145">#9145</a>)</li> <li>authz: Add <code>OnPolicyUpdate</code> callback to <code>FileWatcherOptions</code> to notify when an authz policy is loaded or updated. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9142">#9142</a>) <ul> <li>Special Thanks: <a href="https://github.com/hnefatl"><code>@hnefatl</code></a></li> </ul> </li> <li>xds: Add support for the GCP Authentication HTTP Filter, which automatically fetches and attaches GCP Service Account Identity JWT tokens to outgoing RPCs. <ul> <li>This feature can be enabled by setting environment variable <code>GRPC_EXPERIMENTAL_XDS_GCP_AUTHENTICATION_FILTER=true</code>. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9119">#9119</a>)</li> </ul> </li> <li>xds: Add support for xDS-based HTTP CONNECT proxies. <ul> <li>This feature can be enabled by setting environment variable <code>GRPC_EXPERIMENTAL_XDS_HTTP_CONNECT=true</code>. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9151">#9151</a>)</li> </ul> </li> <li>xds: Add support for <code>contains_match</code> in route header matchers. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9223">#9223</a>)</li> </ul> <h1>Bug Fixes</h1> <ul> <li>credentials/alts: Fix panic when processing malformed frames by validating that the message frame length exceeds the message type field size. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9197">#9197</a>)</li> <li>grpc: Fix compilation on Plan 9 targets (<code>GOOS=plan9</code>), broken since v1.81.0. (<a href="https://redirect.github.com/grpc/grpc-go/issues/9255">#9255</a>) <ul> <li>Special Thanks: <a href="https://github.com/Yusufihsangorgel"><code>@Yusufihsangorgel</code></a></li> </ul> </li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/grpc/grpc-go/commit/030ee8becb20ce4315d6bf2dfa26bdd876169dc4"><code>030ee8b</code></a> Update version to 1.83.2 (<a href="https://redirect.github.com/grpc/grpc-go/issues/9375">#9375</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/8668b69c167df908b6b3666dcbf40992b9e932a4"><code>8668b69</code></a> cherry-pick <a href="https://redirect.github.com/grpc/grpc-go/issues/9365">#9365</a> to v1.83.x (<a href="https://redirect.github.com/grpc/grpc-go/issues/9366">#9366</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/a3e952d2b7c973b7ec6357676e55a2a9c9faaa0d"><code>a3e952d</code></a> cherry-pick <a href="https://redirect.github.com/grpc/grpc-go/issues/9346">#9346</a> to v1.83.x and update x/net dependency (<a href="https://redirect.github.com/grpc/grpc-go/issues/9369">#9369</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/58f8fd9a002536548ac96e34621d761b29cc4f3e"><code>58f8fd9</code></a> Change version to 1.83.2-dev (<a href="https://redirect.github.com/grpc/grpc-go/issues/9337">#9337</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/1550d9e0cddb30ce99e61a2102e8294a49461e5e"><code>1550d9e</code></a> Change version to 1.83.1 (<a href="https://redirect.github.com/grpc/grpc-go/issues/9336">#9336</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/ebba6f3f1b206e2b4dc4d1d5a96d18430302c2fe"><code>ebba6f3</code></a> Cherry-pick <a href="https://redirect.github.com/grpc/grpc-go/issues/9258">#9258</a> and <a href="https://redirect.github.com/grpc/grpc-go/issues/9332">#9332</a> into v1.83.x (<a href="https://redirect.github.com/grpc/grpc-go/issues/9335">#9335</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/8cfeca0e1ee5ea0980dcc320e20240fa1079ec77"><code>8cfeca0</code></a> Cherry-pick <a href="https://redirect.github.com/grpc/grpc-go/issues/9331">#9331</a> to v1.83.x (<a href="https://redirect.github.com/grpc/grpc-go/issues/9333">#9333</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/dec6951305e88906696f1d0a00dd2439363bc708"><code>dec6951</code></a> Change version to 1.83.1-dev (<a href="https://redirect.github.com/grpc/grpc-go/issues/9229">#9229</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/4c226daff88f54441d70f710815e07b81fb162b2"><code>4c226da</code></a> Change version to 1.83.0 (<a href="https://redirect.github.com/grpc/grpc-go/issues/9228">#9228</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/c198988aa9297cb9428c7afaaee4363d0082b838"><code>c198988</code></a> Cherrypick 9223 into v1.83.x (<a href="https://redirect.github.com/grpc/grpc-go/issues/9279">#9279</a>)</li> <li>Additional commits viewable in <a href="https://github.com/grpc/grpc-go/compare/v1.82.1...v1.83.2">compare view</a></li> </ul> </details> <br /> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: 修雨 <47820304+PeterGuy326@users.noreply.github.com>
…cted (#204) ## What this does Adds `GOVERNANCE.md`, the release governance charter for this repository: branch protection on `main`, `refs/tags/v*` immutability, the stricter bar for release-cut pull requests, the CODEOWNERS policy, and an incident runbook. It is additive. It does not change any workflow, setting, or rule, and it explicitly subordinates itself to live repository configuration. ## Why this is a new pull request rather than #125 #125 carries the same charter, but its head branch lives in a fork (`waterbro-8/mem`). `.github/workflows/bytefolk-security.yml:36` guards the `codeql` job with: ```yaml if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} ``` `codeql` needs `security-events: write` to upload SARIF, which GitHub does not grant to a `pull_request` run from a fork, so skipping it there is correct. The problem is what skipping produces. Because `codeql` is a matrix job skipped by a job-level `if:`, GitHub never expands the matrix and publishes the check run under the literal, un-interpolated name `CodeQL (${{ matrix.language }})` with conclusion `SKIPPED`. That name matches none of `CodeQL (go)`, `CodeQL (javascript-typescript)`, or `CodeQL (python)`, which `main` requires. Required contexts that are never reported are treated as pending forever. So #125 cannot merge at any number of approvals. `Update branch`, auto-merge, and re-running workflows all fail to change that. Re-pointing the work onto a branch inside `bytefolk/mem` is the only resolution that needs no policy change and grants no new permission, which is why this pull request exists. #125 should be closed as superseded by this one. ## What differs from #125's content The charter is otherwise the same document, but four claims in its Tag immutability and Incident runbook sections did not match the live configuration. They are corrected here. **1. "two active rulesets, neither of which has bypass actors" — false.** | Ruleset | Blocks | Bypass actors | | --- | --- | --- | | `21888356` Protect stable release tags | `update`, `deletion` | none | | `21899500` Restrict stable release tag creation | `creation` | repository role `admin` (`repositoryRoleDatabaseId` 5), `bypass_mode: always` | Read from `GET /repos/bytefolk/mem/rulesets/{id}`, and confirmed via GraphQL `RepositoryRulesetBypassActor.repositoryRoleName`, which returns the string `admin` directly rather than an id that has to be interpreted. The asymmetry is deliberate and is now stated as such: creation stays reachable so a release can always be cut, while published tags are immutable for every role including admin. Immutability is enforced by `21888356`, not by `21899500`. **2. "GitHub exposes no creation timestamp for rulesets" — false.** The individual ruleset endpoint returns `created_at` and `updated_at`, so the pair is orderable: `21888356` at `2026-08-31T00:34:47Z`, `21899500` at `2026-08-31T04:47:11Z` (updated 54 seconds later at `04:48:05Z`). The charter previously declined to say which rule came first on the strength of that incorrect premise. **3. "If no such path exists when a release is needed, that is a blocker" — a path exists.** A repository admin can cut a `v*` tag directly. `v0.1.1` demonstrates it: annotated tag object `c2ecc1c49ff8bbe13b9d7800bc910e4b7ac99b74` dereferences to commit `cc727db0bc72655f299166de1f60756f5c686cc7` and is tagged `2026-08-31T06:32:10Z`, one hour and forty-five minutes after `21899500` became active, by a repository admin. **4. Incident runbook step 4 repeated claim 1.** This is the one with operational consequences. As drafted, a maintainer working a compromised-release incident at 3am would have read that tag creation "has no bypass actors" and that a missing creation path "is escalated, not worked around" — and would have escalated a tag cut that a repository admin can simply perform. The step now says it is an admin action that requires no ruleset change, and that no ruleset change should be made in order to perform it. **Probable cause of the error, now recorded in the document.** The collection endpoint `GET /repos/{owner}/{repo}/rulesets` renders `bypass_actors` as `null` for every ruleset. A reader who trusts that rendering concludes no bypass actors exist anywhere. The corrected section names the per-ruleset endpoint explicitly so the mistake is harder to repeat. ## What was verified and left alone All nine branch-protection values the charter asserts were re-read from `GET /repos/bytefolk/mem/branches/main/protection` and are correct as written, so that section is unchanged: `enforce_admins: true` · `required_approving_review_count: 1` · `require_code_owner_reviews: true` · `dismiss_stale_reviews: true` · `require_last_push_approval: true` · `required_linear_history: true` · `required_conversation_resolution: true` · `allow_force_pushes: false` · `allow_deletions: false` · `bypass_pull_request_allowances: null` One sentence was added to that section to keep the two controls distinct: branch protection having no bypass actors is a separate fact from tag creation having an admin bypass, and conflating them is what makes claim 1 plausible on a first read. The required-check enumeration in that section is unchanged and remains explicitly hedged as "evidence of what runs, not a substitute for the configuration". It is dated 2026-09-03 and does not list `CodeQL (go)`, `CodeQL (javascript-typescript)`, `CodeQL (python)`, or `Dependency review`, all of which are in fact required on `main` today. The hedge already covers this, but a reviewer who wants the list refreshed should say so rather than let it stand as a near-miss. ## Attribution The charter's first commit (`d2600211`, aligning it with the enforced protections) and the `main`-sync merges are PeterGuy326's. The commit tracking the live CODEOWNERS policy and both tag rulesets (`470babed`, 2026-09-03) is waterbro-8's and is credited via `Co-authored-by`. The four corrections above are mine and are not attributed to waterbro-8. ## Checks - Docs-only. Adds one file, `GOVERNANCE.md`. No code, workflow, configuration, or dependency change, so no runtime behaviour is affected. - Title is Conventional and the body links `#124` and `#125` for `pr-policy`. - Head branch is inside `bytefolk/mem`, so `codeql` is not skipped and the three required CodeQL contexts will be reported normally. Refs #124 Refs #125 Co-authored-by: waterbro-8 <318569545+waterbro-8@users.noreply.github.com>
…rawal (#209) ## Summary Resolves #207. Every MinIO image reference in this repository now resolves from `quay.io` instead of Docker Hub. MinIO stopped publishing container images in October 2025 and removed the `minio/minio` and `minio/mc` repositories from Docker Hub entirely, so every reference here is dead. This is not a cosmetic dependency bump. `Validate Agent memory` → `HTTP, CLI and MCP lifecycle` **requires** the `e2e` Compose profile, and `HTTP, CLI and MCP lifecycle` is a **required status context on `main`**. So the registry withdrawal blocked *every* pull request in this repository from merging — not just the ones touching this stack — and no contributor could do anything about it. ## The failure, verbatim ```text minio Pulling minio Error pull access denied for minio/minio, repository does not exist or may require 'docker login': denied: requested access to the resource is denied postgres Interrupted ``` `postgres` reports `Interrupted` in the same step only as a consequence; the job dies during container startup, before any script under test is reached. I confirmed the outage was still live before writing this PR by re-running the failing job on the current head of #205 ([run 34857342711](https://github.com/bytefolk/mem/actions/runs/34857342711), attempt 4), which failed at `2026-09-15T05:52:24Z` with the identical error. ## The fix `quay.io` still serves the same images. Before changing anything I resolved both digests pinned in `docker-compose.test.yml` against quay.io: ```text quay.io/minio/minio @ sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e -> 200 (image manifest list) quay.io/minio/mc @ sha256:a7fe349ef4bd8521fb8497f55c6042871b2ae640607cf99d9bede5e9bdf11727 -> 200 (image manifest list) ``` Both return their manifests, so **no image bytes change**. The digest-pinned test stack keeps its exact digests, the release-tagged deployment stack keeps its exact tags, and only the registry host differs. Same builds, different registry. ### Changed references | File | Service | From | To | | --- | --- | --- | --- | | `docker-compose.test.yml` | `minio` | `minio/minio:latest@sha256:14cea493…` | `quay.io/minio/minio:latest@sha256:14cea493…` | | `docker-compose.test.yml` | `minio-init` | `minio/mc:latest@sha256:a7fe349e…` | `quay.io/minio/mc:latest@sha256:a7fe349e…` | | `docker-compose.yml` | `minio` | `minio/minio:latest` | `quay.io/minio/minio:latest` | | `docker-compose.yml` | `minio-init` | `minio/mc:latest` | `quay.io/minio/mc:latest` | | `deploy/compose/compose.yaml` | `minio` | `minio/minio:RELEASE.2025-04-22T22-12-26Z` | `quay.io/minio/minio:RELEASE.2025-04-22T22-12-26Z` | | `deploy/compose/compose.yaml` | `minio-init` | `minio/mc:RELEASE.2025-04-16T18-13-26Z` | `quay.io/minio/mc:RELEASE.2025-04-16T18-13-26Z` | | `deploy/compose/compose.yaml` | `minio-client` | `minio/mc:RELEASE.2025-04-16T18-13-26Z` | `quay.io/minio/mc:RELEASE.2025-04-16T18-13-26Z` | ### Why the non-CI files are in scope `docker-compose.yml` is the documented local development stack and `deploy/compose/compose.yaml` is the documented self-hosted single-node path. Both reference the same removed repositories. `deploy/compose/compose.yaml` deserves specific mention: **no workflow exercises it**, so it would have kept a broken reference indefinitely and failed on a cold host for an operator following `docs/DEPLOYMENT.md`. The `deploy/compose` `.env.example` / `backup.sh` / `restore.sh` files were checked and carry no image reference of their own. ## Deliberately not changed The `pgvector/pgvector` references. That repository is still present on Docker Hub, and the `PostgreSQL integration` job — which pulls `pgvector/pgvector:pg16@sha256:00ba258a…` straight from Docker Hub on the same runner image at the same time — was **green in all the runs that failed on MinIO**. That is the evidence that this is specific to the MinIO repositories rather than general registry egress, and it is why the fix is scoped to MinIO alone. See #207 for the full run-by-run comparison. ## How this verifies itself The failing job checks out the PR merge commit and runs `docker compose -f docker-compose.test.yml up -d --wait postgres minio`, so on this PR's own head it exercises the changed file directly. `HTTP, CLI and MCP lifecycle` going green here is the proof, and it is also the precondition that unblocks the rest of the queue. ## Out of scope - Removing the `minio/*` dependency entirely (e.g. moving to SeaweedFS) — a separate decision, and the Apache Flink project took that route while Apache Doris took this one. - Pinning `docker-compose.yml`'s floating `:latest` tags. Those are the local development stack, `scripts/validate_deploy.sh` only rejects mutable `latest` in the production deployment files (`deploy/`, `*/Dockerfile`), and tightening them is unrelated to this outage.
## What this changes
One line deleted from `.github/workflows/bytefolk-security.yml` — the
`if:` guard on the `codeql` job. Nothing else in the file or the
repository changes.
```diff
codeql:
name: CodeQL (${{ matrix.language }})
- if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }}
runs-on: ubuntu-24.04
```
Blob size goes 1988 -> 1867 bytes. The deleted line is exactly 121 bytes
including its newline, so the arithmetic accounts for the whole delta:
no whitespace, reordering or annotation change rode along.
## Why
The guard's second clause compares the head repository to the base
repository. It is false for every fork pull request, so the `codeql` job
is skipped.
GitHub does not evaluate a job's `name:` expression when the job is
skipped by its `if:` guard. The skipped job publishes the raw template
string as its check name, so fork PRs in this repository report a check
literally named `CodeQL (${{ matrix.language }})`, which matches none of
the three required contexts `CodeQL (go)`, `CodeQL
(javascript-typescript)` and `CodeQL (python)`.
This is not hypothetical. Two fork PRs by `@sun-970` were measured
through `GET /repos/bytefolk/mem/commits/{sha}/check-runs` after their
first-time workflow runs were approved:
| PR | head | total | success | failed | skipped |
| --- | --- | --- | --- | --- | --- |
| #172 | `a29e9163` | 17 | 16 | 0 | 1 |
| #181 | `4a25bd25` | 17 | 16 | 0 | 1 |
The single skip in each is `CodeQL (${{ matrix.language }})`. Both are
otherwise fully green and both report `mergeable: true`, yet neither can
ever merge: the three CodeQL contexts are required and nothing the
contributor does produces them. The un-interpolated name is a symptom of
the skip, not a separate defect — on `bytefolk/digital-employee#250` the
same expression interpolated to `CodeQL (javascript-typescript)` as soon
as the job actually ran.
## Why deleting the guard rather than adding a `codeql-fork` job
`bytefolk/digital-employee#250` solved this by adding a second job with
the inverted guard. That job is identical to the baseline `codeql` job
apart from the guard and the language matrix, so a second lane
duplicates roughly 37 lines to express what deleting one line already
says.
The guard is also provably redundant for every trigger other than a fork
PR:
- `push`, `schedule`, `workflow_dispatch` — the first clause
`github.event_name != 'pull_request'` is already true.
- Same-repository `pull_request` — the second clause is already true.
- Fork `pull_request` — the job was skipped; it now runs. **This is the
only behavioural change.**
## Evidence that CodeQL actually works on a fork `pull_request` run
`bytefolk/digital-employee#250` is a fork PR (head
`PeterGuy326/digital-employee:feat/issue-245-memory-config`, sha
`abb2d58b29710927742c828a510c419c7c53efb8`). Its `codeql-fork` job
concluded `success` — check runs `102757987331` (84s) and `102757703884`
(86s).
That job declares `permissions: security-events: write` and contains
**no** `continue-on-error` on the job or on any step. A `success` job
conclusion therefore means every step succeeded, including `Analyze` —
and `github/codeql-action/analyze` fails with HTTP 403 when
`security-events: write` is absent. So SARIF upload from a fork
`pull_request` run is confirmed, not assumed.
Fork `pull_request` runs still receive no secrets and read-only
`contents`. All ByteFolk repositories are public.
## Tradeoff, stated plainly
After this change, fork PRs build untrusted code in a job holding
`security-events: write`. The run still has no secrets and read-only
`contents`, and every other required check in this repository (`Go`,
`Worker`, `Web`, `PostgreSQL integration`, `Web memory and transfer
acceptance`, `HTTP, CLI and MCP lifecycle`, `Workflow, scripts and
Compose`) already builds that same untrusted code, so this adds no new
class of exposure. It is the posture GitHub's own default CodeQL setup
takes for public repositories.
The alternatives were considered and rejected:
- `pull_request_target` would hand a write-scoped token to a workflow
run over attacker-influenced code.
- Self-reporting the three contexts through the Statuses API would
fabricate a required check that never ran.
- Granting contributors organization membership does not help at all:
the guard compares repositories, not author identity.
## What this does not touch
- No `permissions:` block changes. The job keeps exactly `contents:
read`, `actions: read`, `packages: read`, `security-events: write`.
- No required status context, branch protection rule or ruleset is
weakened or removed.
- No action SHA, trigger, matrix entry, step or job other than the
deleted line.
- The pinned `# v4.37.4` annotations are deliberately left alone. They
are the subject of bytefolk/.github#32 and #203, and this PR must stay
disjoint from them.
## Interaction with #203
#203 edits this same file, but only the three `github/codeql-action/*`
annotation lines at 58, 65 and 68, plus `bytefolk-scorecard.yml`. This
PR deletes line 36. The hunks do not overlap, so the two 3-way-merge
cleanly in either order. Neither needs rebasing because of the other.
## Checks
`Workflow, scripts and Compose` runs `actionlint` over every workflow.
Deleting a job-level conditional cannot introduce an actionlint finding;
the resulting YAML keeps `name`, `runs-on`, `timeout-minutes`,
`permissions`, `strategy` and `steps` on the `codeql` job. The release
pin validators in that job (`validate_release_action_pins.sh`,
`test_release_guards.sh`, `test_release_helpers_compat.sh`) all hardcode
`release.yml` and never read this file.
This branch is same-repository rather than a fork, so the PR's own three
CodeQL contexts can go green here — otherwise the fix could not
demonstrate itself.
## Follow-up
The identical guard sits in
`bytefolk/.github/workflow-templates/bytefolk-security.yml`, which is
where every consumer copied it from. A separate template PR is filed so
the fix propagates instead of regressing on the next template sync. Any
consumer that added its own `codeql-fork` lane (`digital-employee`, via
#250) must delete it once the template changes, otherwise two jobs
publish the same check name.
After this merges, #172 and #181 need a branch update rather than a
plain re-run: for `pull_request` events GitHub takes the workflow YAML
from the merge ref, while a re-run replays the workflow version captured
when the run was created. Both are already `state: behind` under
`strict: true`, so they need the update regardless.
Refs bytefolk/.github#35
Co-authored-by: 勒布朗-詹姆斯 <2986253039@qq.com>
## Canonical requirement Refs bytefolk/.github#32 - Canonical Issue URL: bytefolk/.github#32 - Consumed revision: R1 - No automatic close keywords: acknowledged Decision reference: the initial R1 Issue body. It explicitly records that local candidates preceded this prospective publication record; no retrospective approval is claimed. ## Requirement trace | REQ/AC IDs | Changed files / domain | Tests or review evidence | |---|---|---| | REQ-001 / AC-001 | 4 exact-pinned version annotations | Exact expected-byte replacement PASS | | REQ-002 / AC-002 | 2 files in bytefolk/mem | Repository inventory PASS; aggregate 7 repositories, 13 files, 21 lines | | REQ-003 / AC-003 | Existing workflow content and modes | Parsed YAML and comment-stripped bytes identical | | REQ-004 / AC-004 | Current-head CI and independent review | Local independent replay recorded in the canonical R1 Issue linked above; hosted CI collected on head `f464f686` (19 of 20 checks succeed, see Validation); independent human review requested and still pending | ## File domains `.github/workflows/bytefolk-scorecard.yml` (47); `.github/workflows/bytefolk-security.yml` (58, 65, 68). Prepared parent / merge base: `2986fe38175f54d99f15dd38a498708c6ecd88cd` PR base at publication: `87db0dfe0507be2190fe2fdcce0e267be8224f4d`. Since that baseline `main` advanced by six commits through `3c13f04e` (#162, #160, #165, #188, #158, #204) — not only `web/package-lock.json` as previously stated here. None of them touched `.github/workflows/`, so the F9 workflow blobs and the PR diff are unchanged. The reviewed commit and original parent are preserved. Head: `f464f68636adc6bb5295c3818aa6654c46a3caad` — `d2a9ec5` plus one non-forced `Merge branch 'main'` commit (`f464f686`) that brought the branch up to `3c13f04e` so it is no longer `BEHIND`. Verified: `git rev-parse d2a9ec5:.github/workflows/bytefolk-scorecard.yml` and `...:bytefolk-security.yml` return the same blobs (`2058126c`, `48a507e0`) as at `f464f686`, and `git diff main...f464f68` is still exactly these 2 files, `+4/-4`. The comment-only payload is therefore byte-identical to the reviewed commit and the equality proof above holds on the current head. ## Scope and non-goals Correct only `# v4.37.4` to `# v4.37.9` on CodeQL uses-lines pinned to `cdf488f595d80d6e07e03d4674febd5ab45fa938`. The [official tag object](https://api.github.com/repos/github/codeql-action/git/tags/a35ac6e6798d72df5475948b28efb89edc2e19ca) resolves to that existing pin. Action SHAs, permissions, triggers, steps, matrices, other pins, and runtime code are unchanged. ## Validation - Exact commands: `ruby evidence/verify.rb --baseline` and `ruby evidence/verify.rb --committed` from the retained review packet; `git diff --check 2986fe3 d2a9ec5` from this repository. - Observed counts/results: PASS 2/2 files and 4/4 replacements here; aggregate PASS 13/13 files and 21/21 replacements. Baseline intentionally exits 1 after detecting all 21 stale annotations; committed verification exits 0. - Check URLs: collected on head `f464f686` — 19 of 20 checks succeed. The single failure is [`HTTP, CLI and MCP lifecycle`](https://github.com/bytefolk/mem/actions/runs/34807101354/job/103861020551), whose log is `pull access denied for minio/minio` at ~13s: a container-image pull failure in an unrelated job. The same workflow was green on `main` at `3c13f04e`, and the identical failure is present on #198 and #199, so it is not caused by this comment-only change. Root-cause tracking is separate and open. The strict verifier checks the changed-file allowlist; exact old blobs and line inventory; complete expected-byte replacement; absence of stale target annotations; parsed YAML equality; comment-stripped byte equality and SHA-256 digests; whitespace and unchanged modes; one commit with the exact parent; and clean worktrees with no untracked files. All passed. The independent replay is recorded in canonical R1. The verifier and inventory are retained outside repository commits. | ID | REQ/AC | Observable acceptance criterion | Command or manual steps | Environment | Expected | Observed | Status | |---|---|---|---|---|---|---|---| | V1 | AC-001, AC-002, AC-003 | Exact annotations with executable YAML unchanged | `ruby evidence/verify.rb --committed` | Ruby 2.6.10, Psych 3.1.0, isolated review packet | Exact scoped replacements and equality | 2/2 files; 4/4 lines; all invariants pass | PASS | | V2 | AC-004 | Hosted checks on this exact head | Inspect this PR's checks at `f464f686` | GitHub Actions | Applicable checks succeed | 19 of 20 succeed; `HTTP, CLI and MCP lifecycle` fails on `pull access denied for minio/minio` (infra, unrelated job, also failing on #198/#199, green on `main`) | PARTIAL | ## Security and compatibility Documentation annotation only. No dependencies, permissions, credentials, data flows, or runtime behavior change. The diff and commit identity were inspected for public-safe content. No CHANGELOG entry or behavior-documentation update is needed because only explanatory comments change. ## Known limitations Runtime suites, build, coverage, and dependency audits were not rerun for this comment-only change; no runtime test result is claimed. Hosted CI is separate from local equality proof. Two limits now apply: (1) the strict verifier's `one commit with the exact parent` invariant describes the reviewed payload commit `d2a9ec5`, not the current branch shape, which carries two additional `Merge branch 'main'` commits; (2) this PR is **not merge-ready yet** — repository `AGENTS.md` step 6 requires passing CI *and* an approval from someone other than the author, and `HTTP, CLI and MCP lifecycle` is red on the unrelated `minio` pull, so the green-CI half is unmet until that infrastructure failure is fixed. ## Risk and rollback Low-risk annotation correction. Roll back through an ordinary revert of this single commit. There is no migration or release action. ## Product review handoff - Implementation/publication owner: @PeterGuy326 - Automated pre-review result: independent local replay recorded in R1; no human approval implied. - Human final review: PENDING; no human review requested by this publication. - Merge ledger owner: @PeterGuy326 - Product reviewer: @PeterGuy326 - Milestone or release packet: N/A: bounded documentation annotation maintenance - Merge, CI, release, and model judgment do not accept or close the Issue: acknowledged ## Maintenance update (2026-09-14, @waterbro-8) Records written by the maintainer account, not by the implementation owner: - `f464f686 Merge branch 'main'` was pushed to this head branch (non-forced, `main` at `3c13f04e` is an ancestor of the head) to clear the `BEHIND` state this PR's own body said blocked merging. No workflow file content changed: both blobs are identical to `d2a9ec5`. - The stale facts above were corrected in place: the recorded head SHA, the "Main advanced only `web/package-lock.json` in PR #192" claim, the `NOT VERIFIED` hosted-CI rows, and the "this is a draft, not merge-ready" note. - This PR was marked ready for review and an independent review was requested. The maintainer account that pushed the merge commit did **not** approve it: `AGENTS.md` step 6 requires an approval from someone other than the author, and a commit author on the head cannot supply that approval for their own push. `@PeterGuy326` remains implementation and merge-ledger owner. Co-authored-by: 勒布朗-詹姆斯 <2986253039@qq.com>
…ies (#181) ## Summary Fixes #179. `GOAL.md` §5 and §6 contain four status statements that list capabilities as missing when they are already merged and reachable on `main`. This PR corrects them to match what the code actually supports. ## Changes ### §5 — 现状与愿景的偏差 table - **跨设备恢复**: Separate `merge_conservative` (done, `merge.go` + `0023_workspace_import_merge.sql`) from 增量同步 and 断点上传 (not done). The old wording made all three look missing when only two are. - **人类可视化**: correction/supersede relations are merged (`0022_memory_relations.sql`, `relation.go`); only audit history remains open. - **数据可移植性**: `merge_conservative` import is merged; update "当前服务只支持 fresh restore" to reflect that merge is now supported. ### §6 — 近期优先级 - **P1**: Split `merge_conservative` (checked) from 增量包/断点上传 (still open). Previously one unchecked item bundled done and undone work together. - **P2**: Check off correction/supersede, 导入历史 and 权限管理界面 — all shipped via PRs #90/#95, #102, #100. ## Evidence Each correction is backed by source-level evidence (file presence + migration content) as documented in #179. No runtime verification was performed; see issue's "Evidence level: E2 — source-level" note. ## Test plan - [ ] Review each corrected line against the cited source files. - [ ] Confirm §5 rows now separate done from not-done within each capability. - [ ] Confirm §6 checkboxes match the merged PR list. Co-authored-by: 勒布朗-詹姆斯 <2986253039@qq.com>
## Problem and result Refs #211 (revision r2) and bytefolk/design-system#29. The Web client had faint light-theme labels, inconsistent control colors and broadly centered reading content. It now derives its palette from the shared design-system source and aligns content by purpose: names/forms/headings start-align, comparable numeric columns and trailing actions end-align, and button contents and complete empty states center. Narrow layouts keep controls reachable. ## Changes - Add a zero-dependency token generator using an unmodified, licensed snapshot of design-system commit `910456901dda74da4d5b0320cd03d36ad18650b0`; verify its SHA-256 and generated output before every Web build. Preserve alpha and derive readable foreground/solid-action pairs from those source hues. - Keep React 19 and existing primitives; add no runtime dependency or peer-range change. A local empty-state adapter follows the shared title/description/action scale. - Restore reading alignment across navigation, files, filters, forms, cards and dialogs; keep localized confirmation labels visible when omitted by callers. - Use a device-width viewport, wrap provider/detail actions, and keep permission tables locally scrollable on phones. Theme browser chrome follows computed tokens. - Update Unreleased changelog. API, routes, storage and authorization behavior are unchanged. ## Validation With locked dependencies (`cd web && npm ci`), `make test-web` passed: type/lint/build and the existing localization, theme, enrichment, memory, managed embedding and transfer acceptance. Unit tests: 7 files / 69 passed; root independently reran the 2 confirmation regressions. The token check verifies 334 generated/composited pairs at >=4.5:1. Actual browser acceptance captured 82 states across both themes at desktop and 390px touch-mobile widths, covering populated/empty views, dialogs, menus, file/memory/task details, providers, permissions and transfer. All 4,758 sampled visible-text pairs met the selected contrast threshold, with no JavaScript errors or unexpected document overflow. The mobile permission table was actually swiped to its trailing action and the confirmation opened. Root independently inspected the running Web client. A separate source/render review caught and verified the failed-thumbnail badge fix (9.23:1 light /10.14:1 dark). A further12 primary/danger/disabled normal+hover samples reached at least5.55:1; true touch scrolling also kept file-list names and numeric columns reachable. This is fixture-based UI acceptance: all API responses came from MSW; it is not a live-backend integration result. Private screenshots remain local. ## CI dependency and review status Keep this PR **Draft** until required current-head CI passes. The preceding head's HTTP/CLI/MCP lifecycle check failed before application tests because the pinned MinIO image could not be pulled from Docker Hub. The separate fix is #209 (issue #207); it is not copied into this UI diff. Other green checks do not waive that dependency. Current-head results must be read independently after this push. No deployment or formal human approval is included. Revert the scoped commits to roll back; no migration is required. ## Current-head hosted result All checks have finished on `7d941998167c4c6dadd27be348d9b96e1ec28e03`. The only failing check is [HTTP, CLI and MCP lifecycle](https://github.com/bytefolk/mem/actions/runs/35047528915/job/104640536818); all other check entries succeeded, including Web and Web memory/transfer acceptance. The failing job stops while starting isolated dependencies: `minio/minio` reports pull access denied before the application tests. This matches the separate registry fix in #209. The PR remains Draft pending that dependency and a fresh successful CI run. Totoro received the review bundle and explicit blocker status, with successful message delivery verified. This is a handoff, not formal approval.
…cessor to #170) (#199) ## Tracking record and provenance Refs #122 — bounded release-validation readiness, not publication or completion of the release issue. Canonical draft successor to #170. Original author `sun-970` and maintainer commits are preserved in ancestry. #170 remains open with its original discussion and reviews; no original review is transferred as an approval of this candidate. - Original/final source head: `fa2c30cc693bc0ae1e679e7d108d59aef1bd4007`. - Successor head: `260710d69a66f919520e5a4dccc3749335eb95fc`. - Integration commit `896aedb0069f688db3c46702147cf9ea7e015ba9` has normal merge parents, in order: source `fa2c30cc693bc0ae1e679e7d108d59aef1bd4007` and actual canonical main `2986fe38175f54d99f15dd38a498708c6ecd88cd`. - Final successor tree: `5f1313f778ae2dc964c20d350b8829a365852100`. - The integration merge was conflict-free. Its only tree additions over source were main's unchanged `.github/workflows/bytefolk-security.yml` and `.github/workflows/bytefolk-scorecard.yml`; source files remained exact at that integration commit. The subsequent `260710d` adds only the separately authorized output-path safety fix and regressions described below. - The lockfile retains #192 source `11e02e21ef2c3dbd2dae26e4376872e54e78ecb5` with its `cherry-pick -x` traceability. No original commit was rewritten. ## Summary and acceptance criteria CHANGELOG comparison links must use the exact preceding version and release endpoint. Missing predecessors fail closed; exact release-tag links remain valid. GNU/Linux checksum enumeration must process each basename separately, accept the correct six assets in a directory with spaces, reject an empty set with an explicit diagnostic, and emit no manifest for invalid input. An independent preflight then reproduced a separate unchanged-baseline gap: an existing `mem-mcp-checksums.txt` symlink to a directory made `mv` publish the temporary manifest outside the asset directory. A later checksum failure did not undo that write. This was NOT introduced by the basename fix and was NOT fixed at original head `fa2c30cc`. This successor now rejects all existing manifest paths (including dangling symlinks) before hashing and immediately before publication, preserving existing paths and external data. Staging still uses randomized `mktemp`, not a predictable filename. The canonical successor resolves the separate CI execution-path gate: main requires three CodeQL language contexts, but the existing workflow skips fork PRs. This same-repository candidate uses the existing allowed path without editing security permissions, fork restrictions, required checks or tests. Changed files against main: `CHANGELOG.md`, `scripts/generate_release_checksums.sh`, `scripts/test_release_guards.sh`, `scripts/validate_release_version.sh`, `scripts/test_release_checksum_output_safety.sh`, `web/package-lock.json`. No security workflow differs from main. ## Reproduction and attribution On real GNU/Linux, base `7a194f1e` passes the release guards, while pre-follow-up `1624cf74` fails with GNU basename's `extra operand` error because `find -exec basename {} +` batches paths. The fix invokes basename once per path with `\;`. The new comparison regression fails against the base wildcard validator with `wrong compare base v0.0.0: command unexpectedly succeeded`. The earlier macOS `find -printf` failure was not caused by the original comparison-link patch: its checksum script was byte-identical to base. [Public correction and evidence](#170 (comment)). Do not confuse the Bash compatibility suite's find stub with actual GNU semantics; the full guard suite uses real GNU find/basename/sha256sum. Output-safety negative controls: the new focused regression fails on both canonical main `2986fe38` and pre-safety integration head `896aedb0` with `symlink-directory: output publication changed existing data or created an unexpected file`. The fixed tree passes seven cases with path spaces: symlink-to-directory, symlink-to-file, dangling symlink, existing directory, existing regular file, an output symlink introduced during hashing, and a pre-existing template-shaped temporary symlink. File-content snapshots verify external data and existing outputs are preserved; the late-symlink case also verifies private staging cleanup. This is bounded path-safety validation, not a claim of atomic defense against a hostile process concurrently replacing paths after the final check; release staging must remain controlled by the release job. ## Validation ledger Environment: isolated Linux aarch64, Linux 6.8, GNU find 4.9.0/coreutils 9.4, Bash 5.2.21, Node 24.13.0/npm 11.6.2. The Node download is checksum-verified. Fresh exact Git bundle clone, two CPUs, GOMAXPROCS=2 and GOFLAGS=-p=1. | Command/check | Expected | Actual | | --- | --- | --- | | `git merge-base --is-ancestor fa2c30c HEAD` | Source ancestry retained | PASS | | Diff source..integration commit excluding the two unchanged main workflow additions | Source files exact before new safety fix | PASS, empty diff | | `git diff --stat 896aedb HEAD` | New baseline safety fix only | PASS, four scoped files: generator, focused tests, full-suite hook, changelog | | Diff main..HEAD for all security/release/publish/policy/acceptance workflows | No workflow changes | PASS, empty diff | | Root: `bash scripts/test_release_guards.sh` | Comparison and six-asset/empty-set guards fail closed | PASS, new comparison-link and full guard PASS | | `bash scripts/test_release_checksum_output_safety.sh` | Existing output paths fail without external writes; random staging remains safe | PASS, seven focused cases on final tree | | `bash scripts/test_release_helpers_compat.sh` | Collection compatibility | PASS | | `bash scripts/test_validate_release_action_pins_compat.sh` | Official action pin compatibility | PASS | | `bash scripts/validate_release_version.sh 0.1.1` | Version surfaces agree | PASS | | `shellcheck scripts/generate_release_checksums.sh scripts/test_release_checksum_output_safety.sh scripts/test_release_guards.sh scripts/validate_release_version.sh` | No shell diagnostics | PASS, ShellCheck 0.11.0 on macOS | | From `web/`: `npm ci --registry=https://registry.npmjs.org --fetch-timeout=45000` | Locked install | PASS, 401 installed packages | | `npm run audit --registry=https://registry.npmjs.org` | Both unchanged thresholds pass | PASS, zero vulnerabilities | | `npm test` | Application regressions pass | PASS, 67 tests / 6 files | | `npm run lint` / `npm run typecheck` / `npm run build` | Static validation and build pass | PASS, existing large-chunk warning only | | `git diff --check 2986fe3 HEAD` | Clean diff | PASS | | Canonical successor CI and CodeQL | All required named contexts execute and pass | PENDING at draft creation; no all-green claim | ## Tests, coverage and known limits The source-head [CI](https://github.com/bytefolk/mem/actions/runs/34437665487) and [acceptance](https://github.com/bytefolk/mem/actions/runs/34437665500) passed; CodeQL was skipped there and did not satisfy its required contexts. Those runs are source evidence, not the canonical successor's CI or review. Coverage percentage was not remeasured. The new output-path safety regression runs through the existing release-guard CI command; no job or check is removed. Full stock-macOS release-guard portability is not claimed: existing BSD `wc -l` padding affects a row-count assertion. The full suite is validated with real GNU tools. The existing large-chunk build warning remains. Windows, browser, Go/process and database acceptance use unchanged CI. No temporary macOS Go executable is run; fixtures are disposable and create no real release. ## Risk, rollback and review Build/release-validation/dependency maintenance, no API/CLI/MCP authorization, storage or migration contract change. `[Unreleased]` documents the behavior. No custom repository secret is referenced by PR workflows; CodeQL uses its existing security-events upload permission. Release/npm publication and Scorecard are not triggered by these candidate branches. No tag, release, original-PR closure, main merge, protection change or formal approval occurs. Rollback is to leave this draft unmerged; no deployed behavior changes. Draft pending exact-head required CI and independent review. The Owner relayed an independent preflight PASS for the original comparison/enumeration delta; that preflight found the baseline output-symlink gap and does not cover this new safety commit. Fresh review of `260710d` remains required. Original human-authored commits are retained; automated assistance helped with maintainer remediation and validation evidence. --------- Co-authored-by: liyuanyang <liyuanyang@users.noreply.github.com> Co-authored-by: waterbro-8 <318569545+waterbro-8@users.noreply.github.com> Co-authored-by: 勒布朗-詹姆斯 <2986253039@qq.com>
#198) ## Tracking record and provenance Refs #122 — bounded CI/release-readiness follow-up, not completion or publication of that release. Canonical draft successor to #169, with the original author's `sun-970` commits and maintainer follow-ups retained unchanged in ancestry. The original PR stays open; its reviews and discussion remain authoritative history, not an approval of this successor. - Original/final source head: `5c3a4a75ab96bed4c046c0822ebc76a87f215cda`. - Successor head: `5c3a4a75ab96bed4c046c0822ebc76a87f215cda`. - Source and successor tree: `9d8a127375fd8e945113e06ae88983a1328b9fae`. - Current canonical main: `2986fe38175f54d99f15dd38a498708c6ecd88cd`, already an ancestor. A normal merge reports `Already up to date`; no empty commit, cherry-pick reconstruction, rebasing, or force push was used. - The audited lockfile retains #192's provenance from `11e02e21ef2c3dbd2dae26e4376872e54e78ecb5` (`cherry-pick -x` in ancestry). ## Summary and acceptance criteria The Web CI job must run its unit tests. Recognized transient npm audit failures may retry, but vulnerabilities, unknown errors, failed spawns, signals and timeouts must remain failures. Successful audit output must remain visible, including below-threshold findings. The Windows evidence helper must complete its report and preserve a nonzero audit exit status. This successor changes no source file relative to #169's exact source head. It exists because the canonical security workflow skips the entire CodeQL job on fork PRs while main requires three language-specific CodeQL contexts. A same-repository candidate executes the existing supported path; no security workflow, permission, required check, audit threshold, or fork restriction is modified or waived. Changed files against main: `.github/workflows/ci.yml`, `CHANGELOG.md`, `scripts/test_win_audit_verify.mjs`, `scripts/win-audit-verify.bat`, `web/audit-retry.mjs`, `web/audit-retry.test.mjs`, `web/package.json`, `web/package-lock.json`, `web/vite.config.ts`. ## Validation ledger Environment: isolated Linux aarch64, Linux 6.8, GNU find 4.9.0/coreutils 9.4, Bash 5.2.21, Node 24.13.0/npm 11.6.2; checksum-verified official Node archive. Fresh Git clone from an exact local bundle, two CPUs, GOMAXPROCS=2 and GOFLAGS=-p=1. Tests use disposable fixtures, not production data or secrets. | Command/check | Expected | Actual | | --- | --- | --- | | `git diff --exit-code 5c3a4a7 HEAD` | Exact source tree | PASS, no differences | | `git merge-base --is-ancestor 2986fe3 HEAD` | Current main included | PASS | | From root: `bash scripts/test_release_guards.sh` | Release guards fail closed | PASS | | `bash scripts/test_release_helpers_compat.sh` | Collection compatibility | PASS | | `bash scripts/test_validate_release_action_pins_compat.sh` | Official pinned actions and compatibility | PASS | | `bash scripts/validate_release_version.sh 0.1.1` | Version surfaces agree | PASS | | From `web/`: `npm ci --registry=https://registry.npmjs.org --fetch-timeout=45000` | Locked install | PASS, 401 installed packages | | `npm run audit --registry=https://registry.npmjs.org` | Both unchanged thresholds pass | PASS, zero vulnerabilities, both reports printed | | `npm test` | Application and audit regressions pass | PASS, 104 tests / 7 files, including 37 audit regressions | | `npm run lint` / `npm run typecheck` / `npm run build` | Static validation and production build pass | PASS, existing large-chunk warning only | | `git -c core.whitespace=blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol diff --check 2986fe3 HEAD` | Clean diff, intentional batch CRLF retained | PASS | | Canonical successor CI and CodeQL | All required named contexts execute and pass | PENDING at draft creation; no all-green claim | ## Tests, coverage and known limits The original successful-report regression was red before the fix (1 failed / 36 passed). Existing exact-source [Web CI](https://github.com/bytefolk/mem/actions/runs/34438230117/job/102747885693) passed 104 tests including 37 audit regressions. Existing real [Windows CI](https://github.com/bytefolk/mem/actions/runs/34438230117/job/102747885554) passed four native batch-helper regressions, including negative controls for both original defects. These are source-head evidence, not independent review or substitute results for the new canonical workflow execution. Coverage percentage was not remeasured. A real-registry Windows audit has not been requalified; its helper tests use local npm.cmd fixtures. The unchanged five-second process fixture timeout reproduces on both pre-follow-up and fixed heads on the managed macOS host; Linux is the validated environment. The existing large-chunk build warning remains. Full Linux process/database and browser acceptance, and native Windows execution, are delegated to unchanged CI; no temporary Go executable runs on macOS. ## Risk, rollback and review Build/CI/dependency maintenance; no application API, CLI/MCP authorization, storage or migration contract changes. `[Unreleased]` already documents the behavior. The PR-triggered workflows reference no custom repository secrets; CodeQL retains only its existing security-events upload permission. No release, npm publication, Scorecard dispatch, tag, merge, or formal approval is performed. Rollback is to leave this draft unmerged; no deployed behavior changes. Draft until the exact candidate has required CI plus independent review. The Owner reports independent review of the fix deltas is already in progress; this description does not represent that review as completed. Automated assistance produced validation and the maintainer follow-up; the original human-authored history remains intact. --------- Co-authored-by: liyuanyang <liyuanyang@users.noreply.github.com> Co-authored-by: waterbro-8 <318569545+waterbro-8@users.noreply.github.com>
) ## Linked draft successor — original #183 remains open Refs #176. ## Current follow-up: `c0421168bd145077bf164f91c0d2b454a79760ef` - Fixed the remaining exported MCP route enum: `tools/list` now includes `lexical`. The in-process MCP regression reproduced the missing enum before the fix and now verifies both schema and `tools/call` HTTP forwarding. All 9 MCP tests pass on Linux; affected-package vet passes. - Added a strict, populated PostgreSQL sequential-upgrade regression and a DB-free embedded-migration continuity guard. Actual PostgreSQL 16.14 / pgvector 0.8.2 advances 23 → 24, verifies lexical backfill and full history, and accepts ordinary production startup afterward. No `AllowMissing` option or migration renumbering. - Cumulative source/base order is #194 → #197 → #195. #197 remains HOLD for text-query planner acceptance; #195 remains HOLD behind it. See `docs/MIGRATION_SEQUENCE.md` for deployment and existing-gap recovery boundaries. - Tests ran at `2f2e965b6794863d7f5a38a748262da4691beb35`; this final head only corrects the documented verification command to `scripts/verify.sh integration`. Fresh exact-head CI and independent review remain required. The earlier evidence below is historical, not a fresh-head approval. Preserves @sun-970 / liyuanyang's complete authored chain through `13ebe9efa6ba3c733199d374e8db3d107f598ca2` for #176. This draft makes the bounded reviewed corrections accessible; it does not replace independent review, CI, or human approval. Do not close #183 before a replacement is verified and merged. The original fork's Git-data write returned HTTP 404 and its repository permissions report `push:false`. No ACL override was attempted. This canonical branch preserves original commit identities and hashes. Added blobs, trees, and commits were checked against local Git hashes; no force update was used. ## Corrections - `scripts/verify.sh`: expect migration 24, matching this branch's lexical migration. The former expectation of 23 caused the PostgreSQL validation failure. - Refresh audited Web development dependencies, traceable to #192 commit `11e02e21ef2c3dbd2dae26e4376872e54e78ecb5` via a separate `cherry-pick -x` commit. Audit threshold unchanged. - No additional search/ranking changes beyond original #183. ## Validation at head `3d885a8427e06fd7175011ef0188a06f32028a3f` - PASS: migration to 24 on PostgreSQL 16.14 / pgvector 0.8.2 and PostgreSQL 17.10 / pgvector 0.8.3. - PASS: `TestLexicalSearchWithoutWorker`, five cases: lexical without worker, text/auto fail closed, CJK trigram, path restriction. Go tests cross-compiled for Linux and executed against real disposable PostgreSQL with `GOMAXPROCS=2` and serial package builds. - PASS: audited lockfile check; shared fix from #192 remains explicit, not attributed to this feature. - NOT CLAIMED: provider-backed vector retrieval or production benchmark quality. - REQUIRED: fresh CI on this exact head and independent review. Original-head CI/review is not approval of this draft. Original feature scope: model-free file-corpus lexical route, migration 0024, API/CLI/docs, managed-provider bypass. Scope excludes tokenizer, generation lifecycle, and ranking redesign.
) (#196) ## Linked draft successor — original #184 remains open Refs #175. Preserves @sun-970 / liyuanyang's authored chain through `89bb12bdf2ae5edbdfa17260953ec6352ab9239f` for #175. Do not close #184 before a replacement is independently verified and merged. This draft remains HOLD for live acceptance. Source-fork Git-data writes returned HTTP 404, with repository `push:false`; no ACL override was attempted. The canonical branch preserves original commit hashes and identities. Added blobs, trees, and commits were individually hash-verified; no force update was used. ## Bounded corrections - Fail closed on ambiguous cross-workspace mappings, unknown result paths, malformed responses, non-finite scores, and failed requests; retain an error artifact and exit 2. - Map the shipping folder `path` plus file `name`; do not silently discard unknown hits or infer tenant identity from snippets. - Vector mode sends `route=text`; lexical mode sends `route=lexical` with null provider/model/dimension metadata. Do not claim `auto` is lexical/vector hybrid. - Reject structured-memory queries this file-search endpoint cannot serve. Document the existing file-only `profile-text-v1` fixture as the bounded corpus. - Remove hostname collection and invented provider/index identity. Configuration labels remain explicitly operator-declared, not server-verified. - Carry #192 audit remediation as a separate `cherry-pick -x` of `11e02e21ef2c3dbd2dae26e4376872e54e78ecb5`; audit threshold unchanged. ## Validation at `651bec1679c50a9cd07cf77b27b5556c20e3273e` - PASS: Python 3.11.14, `python3.11 -m unittest discover -s benchmarks/recall/tests`: 39 tests, including the reproduced fail-closed regressions and a loopback HTTP fixture. - PASS: `python3.11 -m benchmarks.recall verify`: deterministic harness and intentional leakage failure gate. - PASS: Web audit with the explicit shared fix. - NOT VERIFIED: real memd retrieval, actual embedding-provider quality, real index selection, production latency, or full structured-memory corpus acceptance. The HTTP handler is a fixture, not memd; its timing is not live benchmark evidence. ## Exact remaining live prerequisites (no external provider authorized) 1. An isolated, authorized test deployment of real memd and its Worker, with PostgreSQL/pgvector and ingest dependencies configured, plus a token verified to belong to the test workspace. No existing user deployment or provider credentials have been used. 2. Ingest all five synthetic files from `benchmarks/recall/data/profile-text-v1/corpus.jsonl`, preserving their full paths and contents, into that workspace. The producer is not an ingestor. Confirm indexing completed and file/result identities match the fixture. 3. For the bounded fixed-text experiment, use the same locally available, explicitly selected 768-dimensional text embedding model for corpus and query. Verify the corpus/provider metadata and which active generation or fixed table the server actually uses. A label passed to the producer proves none of these facts. No paid provider, external endpoint, model download, or provider configuration was enabled by this correction. 4. Execute all four file queries through real `/v1/search` with `--mode vector`, retain sanitized rankings, then score with `run --rankings` and record the exact memd head, actual model/dimension/index, environment, and errors. An empty/error run does not satisfy live acceptance. 5. Model-free lexical is a separate optional real-server experiment requiring #183's server capability (draft successor #194); it cannot establish vector quality. Full v1 structured-memory acceptance remains unsupported by this producer and must not be reported as passed. Fresh exact-head CI and independent review/human approval remain separate required gates. No fake or paid live run is substituted for the missing evidence.
Squash merge PR #214.
Refs #111 ## Requirement and scope Re-lands #147 onto current `main` as an organization branch. #129/#147 were closed under the 2026-09-03 fork-workflow decision, not as a judgment that the extraction was wrong. Blocker PR #108 is already merged. Preserves qoder behaviour: same memories payload shape, same `Idempotency-Key` derivation for a canonical absolute root, same stdout summary, same cursor file format/location. Adds the OS-backed cursor lock from the #147 follow-up so concurrent writers do not share a `.tmp` name. ## Changes - New `server/internal/ingest` package: walk, per-path cursor (atomic rename, shrink-reset), `--dry-run`/`--limit`, closed failure codes, report aggregation. - `mem ingest qoder` is a thin connector (parser + HTTP upload). - OS advisory lock around cursor load/save (`cursor_lock_*.go`). - No `fsnotify`, no `--watch` (#110 stays a successor). ## Validation ledger | ID | Criterion | Command | Status | | --- | --- | --- | --- | | V1 | Qoder tests with import-path changes | `go test ./cmd/mem -run Ingest` | NOT VERIFIED locally — host Go 1.22, module requires 1.25 | | V2 | Core fixtures: dry-run, shrink-reset, 409 degrade, corrupt cursor | `go test ./internal/ingest` | NOT VERIFIED locally — same toolchain gap | | V3 | `git diff --check` | local | PASS | | V4 | No cobra/stdout in the core package | source review of `server/internal/ingest` | PASS | Independent review still required. No merge or issue close. Original extraction: @waterbro-8. Cursor lock follow-up: @sun-970 / liyuanyang. Canonical-path identity follow-up: 勒布朗-詹姆斯. --------- Co-authored-by: waterbro-8 <waterbro-8@users.noreply.github.com> Co-authored-by: liyuanyang <liyuanyang@users.noreply.github.com> Co-authored-by: 修雨 <47820304+PeterGuy326@users.noreply.github.com>
## Summary Completes the work [#213](#213) left undone against [#173](#173). - Migration **0025** (0024 is already lexical from #194) adds cosine HNSW indexes on `embeddings_text` (768), `embeddings_visual` (512), and `embeddings_face` (512) with `vector_cosine_ops`. - Shipping **text** search no longer uses `DISTINCT ON (f.id) ORDER BY f.id, distance` as the primary plan. That shape cannot use HNSW. It now walks `ORDER BY embedding <=> $1 LIMIT n`, keeps the first sighting of each file, excludes selected files, and **falls back** to the original exact `DISTINCT ON` query if a bounded scan underfills (one file owning many near chunks). - Relator text neighbors use the same continuation/fallback. - Visual already matched HNSW. Face clustering stays in-process; the face index is DDL only. - `index_generation_vectors` is not indexed (scope boundary). - Transactional `CREATE INDEX` (not `CONCURRENTLY`): a failed concurrent build leaves an `INVALID` index that `IF NOT EXISTS` will skip. - Wrong dimensions fail at the `vector(N)` column. Recall is **not** claimed; harness is [#175](#175). Does not reopen #213. #197 remains the earlier HOLD attempt; this branch is based on current `main` (schema 24) and takes 0025. ## Changes - `server/internal/db/migrations/0025_ann_hnsw_indexes.sql` - `server/internal/search/search.go` — text continuation + exact fallback - `server/internal/relator/relator.go` — same policy - `TestHNSWMigrationPostgres` — populated 24→25→24→25, ingest, dimension rejection, EXPLAIN - `TestTextANNFileSemanticsPostgres` — 101-chunk file still returns 10 eligible files - `scripts/verify_hnsw_indexes.sh` + `scripts/verify.sh` head 25 - `docs/VALIDATION_HNSW.md`, SPEC, CHANGELOG ## Validation ledger | ID | Criterion | Command | Status | | --- | --- | --- | --- | | V1 | Server builds, unit contracts | `make test-server` | Pending CI (sandbox has Go 1.22; module requires 1.25) | | V2 | Worker | `make test-worker` | Not affected | | V3 | Web | `make test-web` | Not affected | | V4 | Race | `make test-race` | Pending CI | | V5 | Fresh schema, rollback, PostgreSQL | `make test-integration` | Pending CI — `EXPECTED_MIGRATION_HEAD=25`; `TestHNSWMigrationPostgres` + `verify_hnsw_indexes.sh` | | V6 | DB race | `make test-integration-race` | Pending CI | | V7–V9 | Acceptance / MCP / visual quality | — | Not affected | | V10 | Recall | `make test-recall` | Not measured. Recorded harness: #175 | | Text semantics | 101-chunk file still yields k files | `TestTextANNFileSemanticsPostgres` | Pending CI | | Planner | EXPLAIN uses HNSW for text cosine-order and visual | `TestHNSWMigrationPostgres` + `scripts/verify_hnsw_indexes.sh` | Pending CI. No `enable_seqscan=off`. | Local sandbox could not run Docker or download Go 1.25, so EXPLAIN was not executed here. CI `memory-validation.yml` / `verify.sh integration` is the evidence path. ## Design notes - Defaults `m=16`, `ef_construction=64`. No iterative-scan GUC. - Empty `uuid[]` exclude lists are never sent as SQL NULL (`ANY(NULL)` would drop all rows). - Editing 0001/0019 is comment-only. Goose does not checksum like Flyway. Fixes #173 --------- Co-authored-by: waterbro-8 <318569545+waterbro-8@users.noreply.github.com>
…) (#216) ## Requirement and scope Re-lands #157 onto current `main` as an organization branch. #157 was closed because the fork head could not carry CI, not because the work was rejected. Refs #151. Implementation owner on the issue is @waterbro-8; human review owner is @Bindy-lbb. Original implementation: @sun-970. ## Changes - Release workflow builds `memd`, `mem-migrate`, `mem-healthcheck`, and `mem` for linux/darwin amd64/arm64 in addition to `mem-mcp`. - Two checksum manifests: `mem-mcp-checksums.txt` (6) and `mem-checksums.txt` (16). The post-#199 output-path protections (no process-substitution find, no `wc -l`, refuse existing/late output symlinks, private mktemp staging) are kept and applied to both manifests. - `/v1/version` exposes distinct `version` / `revision` / `contract` fields; CLI `mem version` prints them and still redacts the server URL. - Docker image and DEPLOYMENT.md first-run notes from #157. ## Validation ledger | ID | Criterion | Command | Status | | --- | --- | --- | --- | | V1 | Checksum output safety | `bash scripts/test_release_checksum_output_safety.sh` | PASS | | V2 | Release guards | `bash scripts/test_release_guards.sh` | PASS | | V3 | Bash 3.2 helper compat | `bash scripts/test_release_helpers_compat.sh` | PASS | | V4 | `git diff --check` | local | PASS | | V5 | Go API/CLI tests | `make test-server` | NOT VERIFIED — host Go is 1.22.12, module requires 1.25.0 | | V6 | Built release binaries on six platforms | release workflow | NOT VERIFIED — no tag cut | | V7 | Client revision pin against a published memd | needs published artifact | NOT VERIFIED | No tag, GitHub Release, npm publish, merge, or issue closure is performed by this PR.
…221) ## Summary Lands the **contract-only** MEM-1 envelope for [#220](#220). Pins RoleWeave [#327](bytefolk/roleweave#327) R1 and the P1 correction on [roleweave#345](bytefolk/roleweave#345): `durable-memory.v1` cannot ship `scope` as a free string. Isolation is **workspace + position principal + `memory_scope` + grant/revocation**. Grant rows are reused from `durable-context.v1`; `capability-grant.v1` is a normative pointer (`server=mem`). `grant.mode` is `read` only. Forget uses the mem `delete` token scope plus a workspace role that allows deletion. **No HTTP, SQL migration, or MCP wiring.** Runtime waits for Gate D0. Live E3 evidence is still required before a later PR may claim production recall. This PR does not close #220. ## Changes - `docs/schemas/durable-memory.v1.schema.json` + example - `docs/DURABLE_MEMORY.md` — how grant/revocation enter readback/receipt - `docs/adr/0006-durable-memory-v1.md` - `server/internal/durablememory` — decode (unknown fields / free `scope` fail closed), eligibility, exact readback, permissioned forget, receipt projection - CHANGELOG `[Unreleased]` ## Acceptance | AC | How | | --- | --- | | AC-001 | Required `binding` + `grant` (`grant_id`, `grant_version`, `permission_digest`, `revoked_at`). Schema has no `scope` property. | | AC-002 | Evaluator omits expired / revoked / malformed / superseded / forgotten / out-of-scope. | | AC-003 | `ExactReadback` compares canonical envelope. Pin may preserve TTL eligibility; pin does not restore a revoked grant or another principal. | | AC-004 | `EvaluateForget` requires `delete` token scope + workspace delete role. Failure is `forget_denied`. `Deleted` stays false; never a local fake delete. | | AC-005 | `PhysicalDeleteImplied` is always false. TTL is recall eligibility only. | | AC-006 | Pins #327 R1. No runtime surface. | ## Validation ledger | ID | Criterion | Command | Status | | --- | --- | --- | --- | | V1 | durable-memory contract tests | `go test ./internal/durablememory/ -count=1` (from `server/`) | PASS (0.010s) | | V2 | Worker | — | N/A, no worker change | | V3 | Web | — | N/A, no web change | | V4 | Race | `make test-race` | NOT VERIFIED — CI | | V5 | PostgreSQL / migrations | — | N/A, no migration | | V6–V9 | Acceptance / MCP / visual | — | N/A, contract only | | V10 | Live E3 recall | — | NOT VERIFIED. Required before runtime. Fixtures do not substitute. | ## Design notes - `binding.workspace_id` is the **mem** workspace. `memory_scope` is `/workspaces/<digital-employee instance>/positions/<position_id>`. Those UUIDs are different namespaces. - `permission_digest` is SHA-256 of the canonical `(workspace_id, principal, memory_scope, mode, grant_version)` tuple. - Out-of-scope / malformed probes return an empty receipt (no memory id, locator, or grant block). In-scope denials keep grant status so operators can see why recall stopped. - Recalled text is `trust=untrusted`, `authority=none`. Refs #220 --------- Co-authored-by: asteam-worker <asteam-worker@users.noreply.github.com>
…est (#191) Refs #139. #217 already extracted the qoder checkpoint lock into `server/internal/ingest`. This PR no longer reintroduces `server/cmd/mem/qoder_checkpoint*.go`. It ports the remaining review items onto the live package: - non-blocking `LOCK_EX|LOCK_NB` / `LOCKFILE_FAIL_IMMEDIATELY` - 5s timeout so contention becomes an error (ingest already warns and continues) - subprocess test that a second acquire fails instead of hanging Head: `1271102` on current main. Co-authored-by: 勒布朗-詹姆斯 <318569545+waterbro-8@users.noreply.github.com>
…DC (G5) (#222) ## Summary Follows the G5 sequence for #104: align `@bytefolk/mem-mcp@0.1.2` + `io.github.bytefolk/mem-mcp`, then add an **OIDC** Registry publish path. - Rebase of draft #193 onto current `main` (conflicts resolved; keeps 24-asset checksums from #216). - Does **not** create a tag, does **not** `npm publish`, does **not** deprecate `@fullstack-ai-infra/mem-mcp@0.1.1`. - Adds `.github/workflows/mcp-registry-publish.yml` (`workflow_dispatch`) which: 1. refuses to run unless `https://registry.npmjs.org/@bytefolk/mem-mcp/<version>` exists with matching `mcpName`; 2. logs in with `mcp-publisher login github-oidc`; 3. publishes `io.github.bytefolk/mem-mcp`. - Founder gate: GitHub Environment `mcp-registry` (create + restrict) plus npm Trusted Publisher for `@bytefolk/mem-mcp` / workflow `npm-publish.yml` / environment `npm-release` from #193. Refs #104 #153. Successor to #193 (that PR is DIRTY against main). ## Sequence remaining after this PR merges 1. Founder: prove `@bytefolk` npm ownership ([.github#22](bytefolk/.github#22)), bind Trusted Publisher, create environments `npm-release` and `mcp-registry`. 2. Maintainer: tag `v0.1.2` per `docs/maintainers/releasing.md` (not this PR). 3. `npm-publish.yml` → `@bytefolk/mem-mcp@0.1.2`. 4. Dispatch `MCP Registry Publish` with `0.1.2`. 5. Paste Registry search receipt on #104. ## Test plan - [x] `npm/package.json` is `@bytefolk/mem-mcp` `0.1.2` / `mcpName` `io.github.bytefolk/mem-mcp` - [ ] CI on this head - [ ] Do not dispatch Registry publish until npm 0.1.2 exists --------- Co-authored-by: 修雨 <huyizhou.hyz@alibaba-inc.com> Co-authored-by: liyuanyang <liyuanyang@users.noreply.github.com> Co-authored-by: waterbro-8 <318569545+waterbro-8@users.noreply.github.com>
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.
Closed: used only to import upstream objects for Git Data API.