Repository navigation
Registry canary failed: fresh npx create-objectstack install is broken #16500
Description
Activity
- addedbugSomething isn't workingSomething isn't workingpriority:p1High: required for production / M2High: required for production / M2
on Sep 8, 2026 分诊:
domain:cli/bug/priority:p1/pm:queue/ typeBug—— ⭐ 并且我读了运行日志,根因不是模板要求的两个分支中的任何一个模板写:「Read the run log to see WHICH step failed, because the two have different owners」。读了(run
34084559243,失败作业101626009369"Registry canary (published latest)")。⭐ 根因,逐字
⚠ AuthPlugin failed to load: The requested module '@better-auth/core/db' does not provide an export named 'createLocalAccountIssuer'⇒
npm run build没有失败,服务器起来了。 失败的是AuthPlugin在启动时加载不了 —— 已发布的@better-auth/core不再导出createLocalAccountIssuer。按模板的二分,这属于第二类(#3091 class:一个传递依赖在
^范围内发布了破坏性变更,打中已发布版本)——⛔ 不是#4902/#7644/#8677的脚手架类。⚠️ 但它的形状与模板描述的第二类不同:模板设想的是"auth 或 CRUD 探针失败",实际是插件在 boot 时就没装上,探针失败只是后果。⇒ ⛔ 承接者不要去查探针,去查依赖范围。其余日志证据(同一次启动):
WARN CORE: Core service missing, functionality may be degraded: auth WARN System started with degraded capabilities. Missing core services: auth [sql-driver] DATABASE_ERROR — … 'sys_organization' (SQLITE_ERROR) … no such table: sys_organization WARN SharingServicePlugin: could not enumerate organizations — declared sharing rules were NOT seeded⇒ auth 没装上 ⇒ 它的表从未建出 ⇒ 共享规则播种失败。一条因果链,一个根因。
priority:p1⛔ 不是 p3/p2:已发布的入门路径对每一个新用户都是坏的。
npx create-objectstack@latest是文档给出的第一条命令,而它产出的项目起来之后没有认证。⛔ 不是 p0:⛔ 无安全面、⛔ 不影响任何既有部署(它们锁着自己的 lockfile);且修法是收窄一个依赖范围或补一个 peer 约束 —— 面窄、路径明确。(对比同批 #16645 判 p0:那是每个 SQL 部署 × 任何已认证用户 × 跨租户 × 无规避。)
⭐⭐ 同一份日志同时是另外两张卡的独立实例 —— 这是本次读日志最大的收获
① #16630(
✓ Server is ready打在降级启动上)—— 在这里逐字复现,而且是在 published 制品上:WARN CORE: Core service missing, functionality may be degraded: auth WARN System started with degraded capabilities. Missing core services: auth … ✓ Server is ready Plugins: 30 loaded⇒ #16630 的现场原本取自 objectui CI 的一次 17.2.0 启动。这里是第二个、完全独立的实例:不同触发原因(依赖破坏 vs 版本问题)、不同制品(npm published latest vs 一次 CI 启动)、同一个错误信号。 而且这次它更刺眼 —— 就绪横幅骗过的正是这个 canary 自己:作业最终以 exit 1 结束,靠的是后续探针,⛔ 不是靠那行绿色的
✓。我已把这条读数抄到 #16630 上。② #16693(ADR-0087 转换警告教作者做破坏性收紧)—— 在一个全新脚手架项目上首次启动就触发:
WARN [MetadataPlugin] artifact '…/smoke-app/dist/objectstack.json' predates this runtime's spec (authored engines.protocol floor 17.0.0, runtime spec 17.3.0) — converted 1 site(s) forward via ADR-0087 conversion 'field-required-notnull-explicit' … Update the source to 'storage.notNull: true'.⇒
npx create-objectstack@latest刚生成的项目,第一次启动就被告知它的元数据"predates this runtime's spec",并被指示去写storage.notNull: true。 #16693 指出的正是这条指令在有数据的库上是一次destructive迁移、而警告把它说得像清理弃用通知。⭐ 这份日志证明触发条件比 #16693 卡面说的还宽:不需要一个"写于九月却声明了宽范围"的 app —— 平台自己的脚手架产出的项目就直接命中。我已把这条抄到 #16693(决策箱)上,它把那张卡的"实际业务拉动"一棱从"某个 app"提到"每一个新项目"。验收口径(承接 PR 请照抄进
## 验收备注)- 先复现并定位那个范围:哪个包以
^引入了@better-auth/core,以及它是在哪个版本移除了createLocalAccountIssuer。⛔ 不要直接改代码去适配新导出 —— 先确认这是移除还是改名,两者的修法不同。 - 修法必须同时给出"下次怎么不再发生":Fresh projects: every auth endpoint returns 500 "Cannot set properties of undefined (setting 'modelName')" — fixed in 15.1.1 #3091 类的复发机制是
^范围。⇒ PR 要回答是收窄范围、加 peer 约束,还是别的。⛔ 只把当前这次修好,等于把 canary 变成一个每隔几周响一次的闹钟。 - canary 自己的失败信号要能指认这一类。 ⭐ 本卡模板的二分漏了实际发生的这一类(插件 boot 时加载失败),所以它给出的排查指引会把人引向探针。⇒ 顺手把模板的分类补上第三支:「一个 plugin failed to load 的 WARN 出现在 boot 日志里 ⇒ 依赖范围问题,先查它」。
⚠️ 这一条是.github/workflows/的改动,若承接者认为超出范围,另立卡并回链,⛔ 但不要默认它已被涵盖。 - 阴性对照:修复后重跑 canary,确认
AuthPlugin failed to load消失且 boot diagnostics 的告警数从 4 降下来。⛔ 不要只看作业变绿 —— 见 ①,绿与不绿在这条路径上曾经分不出来。 - ⛔ 不要在本 PR 里修 [finding] the server prints
✓ Server is readyon a degraded boot — the ready signal is independent of the degraded-capabilities warning, and the louder one is wrong #16630 或 ADR-0087'sfield-required-notnull-explicitconversion asserts an implication ADR-0113 abolished — the boot calls it a forward conversion, but its output and the source it prescribes disagree at the storage layer #16693 —— 它们各自有卡;本卡只需在修复后确认那两条 WARN 的成因消失(而不是它们的报告方式改变)。
本席权限声明:分诊席只分类/定级/定车道,以及在能取到读数时取(本次读了 CI 日志)。⛔ 不认领、⛔ 不派发、⛔ 不写代码、⛔ 不合并、⛔ 不裁决决策箱卡。
Generated by Claude Code
- 先复现并定位那个范围:哪个包以
os-project-manager commented
on Sep 8, 2026 CollaboratorMore actionsClaim: PM loop round 71
Session:session_015QE8qk46e5CHJxyQEUjbf8—domain:cliexecution PM seat (#6024), R71
Branch:claude/issue-16500-better-auth-core-range
Worktree:objectstack-issue-16500
Domain:domain:cli
File surface:packages/plugins/plugin-auth/package.json(the@better-auth/corerange) + whatever the range fix requires in that package, and optionally.github/workflows/for the canary's third triage branch (stop on breach; explain in the report)
Container & model:M,mode:subagent,model: opus— cited from THIS round'snode scripts/pm/dispatch-gates.mjs --tier packages/plugins/plugin-auth/package.json, re-derived from a worktree atorigin/main6b7d709b87with noSTALE TREEbanner: "no path-derived mandate … floor sonnet · default opus · ceiling fable".⚠️ CONTRACT_REVIEW_TIERis measured exhausted this session (HTTP 429, seat post5578636779), soopusis also the ceiling the 额度耗尽豁免 permits — ⛔ 不再往下.
Clause-②: no
Thread-read:5578965123
Serial constraints cleared:packages/plugins/plugin-auth/package.json— 1 holder measured across 15 of 15 open PRs, zero unmeasured, per-ref against each PR's own merge-base at 2026-09-08T04:12Z. Positive control fired on both expected PRs (auth-route-ledger.tsin #16761,AGENTS.mdin #16573).⭐ The one holder is PR #15334,
changeset-release/main— and this seat rules it does NOT hold, with the reason stated rather than skipped silently. It is the machine-regenerated "chore: version packages" PR: it rewrites theversionfield of everypackage.jsonin the repo and is regenerated from the changeset set on every merge tomain. Treating it as a serial holder would make everypackage.jsonin the monorepo permanently unwritable, which is not what seat ruling ① is for — that rule exists to stop two authors racing on one file and losing hand-written work. There is no hand-authored edit here to lose, and the release PR rebuilds itself around whatever lands. ⛔ This seat does not touch, chase or merge that PR (「永不合并 Version Packages PR」); it simply is not a hold.⚠️ Sibling in the same package, deliberately not a conflict: PR #16761 (card #16568) touchespackages/plugins/plugin-auth/src/auth-route-ledger.ts— same package, different file. Seat ruling ①: same-package EXEMPT, same-file HARD SERIAL. Measured, ⛔ not assumed: the scan found it on the ledger file and not onpackage.json.
Generated by Claude Code
os-dev-report
{ "issue": 16500, "status": "done", "branch": "claude/issue-16500-better-auth-core-range", "pr": "https://github.com/objectstack-ai/objectstack/pull/16794", "premise_still_valid": false, "summary": "The range half of this card was ALREADY FIXED on origin/main before dispatch: PR #16634 (2e6a2ea4c9, 2026-09-07 22:42Z) pinned the whole better-auth family to an exact 1.7.2 and added check:vendor-export-contract(-resolve). The canary run the card was opened from (34084559243) fired at 04:47Z the same Monday, about 18h BEFORE that fix landed, so criteria 1 and 2 were satisfied in source at dispatch time. Criterion 1 re-measured independently: REMOVAL, not rename -- the @better-auth/core@1.7.3 tarball contains zero create*Issuer* names, so there is no successor to adapt to. PM mechanism assumption 1 CONFIRMED and extended past one level: plugin-auth/package.json is the only in-repo manifest naming better-auth, and better-auth@1.7.2 declares all seven of its own siblings EXACTLY, so nothing transitive re-admits a float; pnpm-workspace.yaml carries the same exact target. This PR therefore delivers criterion 3 only: the canary's failure guidance gains the plugin-failed-to-load branch, ordered first, plus the property that misled this round -- the job installs PUBLISHED artifacts, so a fix on main does not clear it. THE ONE OPEN ACTION IS A RELEASE, AND IT IS NEITHER MINE NOR YOURS: @objectstack/plugin-auth@17.3.0 still holds the latest tag and still declares '@better-auth/core': '^1.7.2', so the on-ramp stays broken for every new user until the maintainer cuts a release by hand (Prime Directive #15). PR uses 'Part of #16500', NOT 'Fixes', so merging leaves the card open for that release.", "tests": "GATES: 33 derived / 33 run / 0 NOT-MEASURED / 0 UNRUN, all exit 0, reconciled via 'dispatch-gates --ran' at d917c083b9 with NO STALE TREE banner (an earlier derivation DID carry one; origin/main had moved, so I merged origin/main and re-derived -- family list identical, full union re-run at the merged head). Exit codes captured before any pipe. TWO GATES CAUGHT REAL DEFECTS IN MY OWN DIFF: (1) check:pnpm-acquisition went red because naming the reproducer as a 'pnpm ...' run put registry-canary -- a job that acquires no pnpm -- into the population of jobs that run pnpm (census 31 down to 30 when the token left); (2) re-spelling it as 'node scripts/check-vendor-export-contract.mjs --resolve' then made it a DISCOVERED GATE FAMILY for dispatch-gates inside a workflow declaring no PR-time event, reddening check:pm-dispatch-gates on its scheduled-only invariant, 4 of 1552 cases. Final wording spells no command at all. ABLATION (criterion 2, committed state, trap-restored, on-disk proof): restored '^1.7.2' in plugin-auth/package.json -- anchor counts before-text 1 to 0 and after-text 0 to 1, blob 4d33eb761e65a0896c296e07eca4bc74eaa6e814 differs from HEAD 7ced877e7e49ea2a439c565a6b11d1b0bdadc7e6. Static leg exit=1 ('a governed vendor range must be an EXACT version'); resolve leg exit=1 reproducing the canary root cause verbatim: '@better-auth/core/db does not export createLocalAccountIssuer, createOAuthAccountIssuer at @better-auth/core@1.7.3, which the declared range \"^1.7.2\" admits. Our lockfile hides this; a consumer's install does not.' Restore verified by hash equality AND empty 'git diff HEAD'. Unablated gate: 'VERDICT: PASS -- vendor export contract (registry resolution), 2 edge(s) verified'. check:partof-closing-keyword run WIRED (PR_BODY + PR_NUMBER + PR_COMMITS_FILE) against the LIVE PR body: exit 0. It first went RED and caught a real trap I had written -- the sentence 'Merging this must not close #16500' carries the keyword bound to the number, which GitHub's parser honours straight through the negation; reworded and re-verified against the live body. printf render verified by executing the edited line with a stub run_url (exit 0, body renders as intended). check:nul-bytes exit 0 plus a direct control-character scan: clean. NOT MEASURED, with its reason: the criterion-4 boot-warning count drop from 4 needs a canary run, and the canary installs published artifacts, so it can only be read after a release -- reporting it as done would be exactly the 'the job went green' reasoning criterion 4 warns against.", "gates": { "derived": 33, "run": 33, "passed": 33, "failed": 0, "not_measured": 0, "unrun": 0, "reconciled_at": "d917c083b9", "stale_tree_banner": false, "reconcile_verdict": "dispatch-gates --ran: 33 derived famil(ies) accounted for -- 33 run, 0 NOT-MEASURED", "extra_non_derived_run": [ "pnpm check:vendor-export-contract-resolve (exit 0; exit 1 under ablation)", "check:partof-closing-keyword WIRED against live PR body (exit 0, after a real red)", "eslint --no-inline-config on the changed file" ], "lint_narrowing": { "population_source": "eslint's own config resolution", "verdict": "the changed .yml matches NO eslint configuration", "file_count_from_json": 1, "errors": 0, "warning": "File ignored because no matching configuration was supplied", "invariance": "no type-aware linting applies and eslint's population excludes .yml, so this diff cannot move any untouched file's verdict" } }, "line_budget": "n/a -- no skills/** path in the diff; nothing published moves", "files_changed": [ ".github/workflows/publish-smoke.yml" ], "deviations": [ "NO CHANGESET, skip-changeset label applied instead -- the dispatch asked for a changeset. Measured: 0 of 82 package manifests list .github in files[], so nothing published moves. Label written via the additive REST endpoint and read back: ['skip-changeset'].", "'Part of #16500' instead of the dispatched 'Fixes #16500' -- merging must leave the card open, because the on-ramp stays broken until a release. Which half remains is stated in the PR's first paragraph.", "Merged origin/main (ed7243d52b) into the branch to clear a STALE TREE banner on the gate derivation, then re-derived (identical family list) and re-ran the whole union at the merged head.", "Clause-2: no -- re-declared from the delivered diff and it holds. The change adds no lenient alias, no double-question-mark fallback, no consumer relaxation; it is guidance prose in a workflow. CONTRACT_REVIEW_TIER exhaustion is not engaged.", "PR body carries two attribution footers: the platform appended its own block on create and again on edit. Not re-posting or looping, per the footer rule.", "Serial re-measured for the file I actually touched (.github/workflows/publish-smoke.yml), which the dispatch's scan did not cover: zero holders across all 24 open PRs; positive control fired on #16761 (auth-route-ledger.ts)." ], "mcp_calls": "0 -- REST was probed open for this seat (HTTP 200 repo-scoped, /rate_limit 15000/hr) and carried every read and write, including filing #16793, opening PR #16794, the label write and this comment", "open_questions": [], "out_of_scope_findings": [ "filed as #16793: publish-smoke's log scan runs AFTER the probes and matches only error/fatal, so a WARN-level boot failure can never be named by the canary itself -- the job exits on a downstream probe. Specimen run 34084559243. scripts/publish-smoke.sh is outside this card's declared file surface and the fix is a new assertion, not a mechanical edit, so it is filed rather than carried here. Linked back to #16500.", "noted, not filed: check:pnpm-acquisition and dispatch-gates both read command-shaped PROSE in a workflow run body as a real invocation. Both are conservative by design and emit actionable messages, and the workaround (point at the workflow instead of spelling a command) is better guidance anyway. Successor: whoever next writes user-facing guidance text into a workflow run body.", "noted, not filed: the canary's dedup search uses state=open, so if #16500 is ever closed while the canary is still red the next run opens a fresh card and the accumulated triage is lost. That is why the PR says Part of rather than Fixes; no code change proposed." ] }
Generated by Claude Code
Premise change, verified at source — and a dispatch error of this seat's own
⛔ This seat dispatched this card against a premise that was already satisfied. The range half was fixed on
origin/mainat 2026-09-07T22:42Z; I dispatched at 2026-09-08T04:10Z, about 5.5 hours later, without re-verifying the premise at source first. The delivering dev caught it and re-measured rather than building against the stale description. ⇒ The error is mine, not the dev's, and it is recorded here rather than quietly absorbed.What is already fixed (measured on
origin/mainb38821d1ce)2e6a2ea4c9 fix(plugin-auth): pin the better-auth family to an exact 1.7.2, and gate the declared range against our own import surface (#16634) packages/plugins/plugin-auth/package.json "@better-auth/core": "1.7.2", ← exact, no caret "@better-auth/oauth-provider": "1.7.2", "@better-auth/scim": "1.7.2", "@better-auth/sso": "1.7.2", "better-auth": "1.7.2", package.json "check:vendor-export-contract" ← present "check:vendor-export-contract-resolve" ← present⇒ Criteria 1 and 2 are satisfied in source.
⚠️ The canary run this card was opened from (34084559243, 04:47Z Monday) fired ~18h before that fix landed, which is why the card reads as it does.⛔ What is NOT fixed — and it is not fixable by any dev
Read from the npm registry directly, with a control:
read value @objectstack/plugin-authdist-tags.latest17.3.0 …its declared @better-auth/core^1.7.2← the caret, still published@better-auth/coredist-tags.latest(control)1.7.3 @better-auth/core1.7.x published (control)1.7.0 … 1.7.2, 1.7.3⇒
^1.7.2admits 1.7.3, and 1.7.3 is whatlatestresolves to today. The in-repo pin does not reach anyone installing from the registry, so the published on-ramp stays broken for every new user until@objectstack/plugin-authis republished.⛔ The one remaining action is a RELEASE, and it is the maintainer's floor (Prime Directive #15) — not this seat's, not a dev's, and not something a merged PR performs. ⇒ This card stays open after PR #16789… correction: after PR #16794 merges, which is exactly why that PR says
Part of #16500and deliberately notFixes.Criterion 4 is ⛔ NOT MEASURED, and cannot be measured yet
The boot-warning count drop needs a canary run, and the canary installs published artifacts — so it can only be read after a release.
⚠️ Reporting it as done on a green job would be precisely the reasoning criterion 4 exists to forbid.Related
- PR fix(ci): the registry canary's triage guidance names the plugin-failed-to-load class #16794 — delivers criterion 3 only: the canary's failure guidance gains the plugin-failed-to-load branch, ordered first, plus the property that misled this round (the job installs published artifacts, so a fix on
maindoes not clear it). - [finding] publish-smoke's log scan cannot name a WARN-level boot failure — it runs after the probes and matches only error/fatal #16793 — filed by the dev as a separable finding: publish-smoke's log scan runs after the probes and matches only
error/fatal, so a WARN-level boot failure can never be named by the canary itself.
维护者速读
⭐ 这张 p1 现在只等一件事:一次发布。 仓内已修(#16634 把 better-auth family 钉成精确
1.7.2并加了两道门),但 npm 上@objectstack/plugin-auth@17.3.0仍是latest、仍声明^1.7.2,而@better-auth/core@latest已经是 1.7.3 ——^1.7.2收得进 1.7.3,所以每一个新用户的安装仍然是坏的,仓内那次修复到不了他们。⛔ 发布是人工地板(Prime Directive #15),本席不碰。PR #16794 用
Part of而非Fixes,正是为了合并后不把这张卡关掉。⚠️ 判据 4(启动告警数下降)未测且暂时无法测 —— canary 装的是已发布产物,得等发布之后才读得到;拿一次绿跑当作它成立,正是判据 4 本身警告的那种推理。⛔ 另外记一笔本席的错:我在 04:10Z 派发这张卡,而它的主判据在 22:42Z 就已经在 main 上修好了 —— 我派发前没有回源头复核前提。dev 复核出来了,没有照着过期描述施工。错在我。
Generated by Claude Code
- PR fix(ci): the registry canary's triage guidance names the plugin-failed-to-load class #16794 — delivers criterion 3 only: the canary's failure guidance gains the plugin-failed-to-load branch, ordered first, plus the property that misled this round (the job installs published artifacts, so a fix on
Reproduced on the PUBLISHED 17.3.0 — the on-ramp is still broken today
Authority — maintainer instruction, verbatim, in this PM session's chat at 2026-09-09T02:2xZ: 「16500 测试一下当前发布的 17.3 有这个问题嘛」
⭐ Answer: yes. Until now this card argued from registry metadata (a
^range that admits 1.7.3). This is the missing leg: an actual runtime reproduction against published artifacts, taken 2026-09-09T02:3xZ. ⛔ No state changed by this comment — no label, no assignee, no dispatch.The chain, each link measured
A — the published artifact really does import the removed symbols. From the
@objectstack/plugin-auth@17.3.0tarball's owndist/:import { createLocalAccountIssuer, createOAuthAccountIssuer } from "@better-auth/core/db"7 occurrences of each name. Declared range in that same published manifest:
"@better-auth/core": "^1.7.2","better-auth": "^1.7.2".B — a new user's fresh install resolves past the break. Empty dir,
npm init -y,npm install @objectstack/plugin-auth@17.3.0, no lockfile of ours in play:resolved @better-auth/core -> 1.7.3 resolved better-auth -> 1.7.3C/D — the import fails at ESM link time, verbatim the canary's error:
SyntaxError: The requested module '@better-auth/core/db' does not provide an export named 'createLocalAccountIssuer'Compare the canary's line from run
34084559243— identical string:⚠ AuthPlugin failed to load: The requested module '@better-auth/core/db' does not provide an export named 'createLocalAccountIssuer'E — positive control, so the failure is the range and not the probe. Same probe, same tree, only
@better-auth/coremoved to the pinned1.7.2:now resolved @better-auth/core -> 1.7.2 linked OK function function⇒ Both symbols exist at 1.7.2 and are gone at 1.7.3. The defect is exactly the caret, and it is live on
latest.What clears it — measured on both refs
ref plugin-auth version declared @better-auth/corenpm dist-tags.latest17.3.0 (published 2026-09-04) ^1.7.2← brokenorigin/main16df17be17.3.0 1.7.2exact ✅changeset-release/mainc0116f9f(PR #15334)17.4.0 1.7.2exact ✅Control: no published
@objectstack/plugin-authversion carries the exact pin — scanned every version on the registry, zero hits. So no existing release fixes this; only a new one does.⇒ Publishing the pending release (PR #15334 →
@objectstack/plugin-auth@17.4.0) carries the exact pin and clears this card. ⛔ That act is the maintainer's by hand (Prime Directive #15) — this seat verified state only, which #15 explicitly permits.⚠️ Criterion 4 (the boot-warning count dropping from 4) remains NOT MEASURED and still cannot be measured before a release, exactly as recorded on 09-08 — the canary installs published artifacts.维护者速读
⭐ 测了,当前发布的 17.3.0 确实有这个问题,而且是今天现场复现的,不是根据元数据推的。
新用户空目录装
@objectstack/plugin-auth@17.3.0,^1.7.2实际解析到 1.7.3,然后插件 dist 里那行import { createLocalAccountIssuer, ... }在 ESM 链接期直接抛错,报文与 canary 日志逐字一致。阳性对照:同一棵树只把@better-auth/core换回1.7.2,两个符号都在、链接通过 —— 所以坏的就是那个^,不是探针。✅ 仓内已经修好了(
main上是精确1.7.2),并且待发布的 #15334 里 plugin-auth 是 17.4.0 + 精确1.7.2—— 也就是说把那个发布发出去就能清掉这张卡。⛔ 另外查过:npm 上没有任何一个已发布版本带精确 pin,所以不存在"让用户装某个老版本绕过"的选项,只能靠发新版。
发布是人工地板,本席只做了状态核验(#15 明确允许
npm view这类验证),⛔ 没动标签、没动 assignee、没派发。
Generated by Claude Code
出口核验(2026-09-09):发版尚未发生,本卡正确留在
pm:awaiting-maintainer维护者回批「我已安排处理」。按状态机出口条款「核验动作确已发生,再摘标加证据评论同笔」,本笔只核验、⛔ 不摘标。
实测三读数(npm registry,本会话直读)
读数 值 判据 @objectstack/plugin-authdist-tags.latest17.3.0 未变 …其声明的 @better-auth/core^1.7.2⛔ 仍是 caret @better-auth/coredist-tags.latest(对照)1.7.3 ^1.7.2收得进它⇒ 入口路径对每一个新用户仍然是坏的。 重跑判据未变:
npm view @objectstack/plugin-auth@latest dependencies.@better-auth/core,读到1.7.2才算已解。⭐ 补上呈报时的置信缺口:发布集合已确认
呈报时我明说未核实「除
plugin-auth外还要同批发哪些包」。现已核(对origin/main):packages/plugins/plugin-auth/package.json是仓内唯一声明better-auth的清单 ——git grep -ln better-auth origin/main -- '*/package.json'单条命中。⇒ 没有第二个包携带这个 caret。- 修复已带 changeset 且已在队列:
.changeset/better-auth-exact-family-pin.md,"@objectstack/plugin-auth": patch⇒ 一次常规 changesets 发布即产出17.3.1并带上精确 pin,⛔ 不需要任何特殊挑拣或手工改版本号。 ⚠️ 上下文,不是阻塞:.changeset/现有 434 条待发,其中 20 条点名plugin-auth。⇒ 这次发布不是单包补丁,是累积发布的一部分;发布集合由 changesets 自行推导。
该 changeset 自陈的一件事,值得你在发版时知道
它明写自己是权宜之计并已标注:upstream 是故意删掉那两个导出的(better-auth/better-auth#10909,issuer-scoped account identity 回退为 opt-in)。采用 1.7.3 意味着要丢掉
sys_account.issuer—— 一个带(issuer, accountId)唯一索引的必填列 —— 退掉启动期回填,并迁移每一个既有部署。⇒ 那是另一张卡、另一个决定;本次 pin 只是让今天的安装能用。⛔ 本卡不覆盖它。出口
发版后重跑 registry canary(或等周跑),确认
AuthPlugin failed to load消失且启动告警数从 4 降下来 —— ⛔ 不要只看作业变绿(#16630:就绪横幅曾骗过 canary 自己)。判据 4 在发版前不可测。确认后由达档总监席以该 run id 为证据摘标并关卡。⚠️ PR #16794 用Part of而非Fixes,正是为了合并后不把本卡关掉。
Generated by Claude Code
✅ VERIFIED FIXED on the published
17.4.0— full on-ramp re-tested end to endAuthority — maintainer instruction, verbatim, in this PM session's chat at 2026-09-09T04:0xZ (⛔ 照抄不译): 「17.4 我已经发布了,你帮我重新测试之前的问题」
@objectstack/plugin-auth@17.4.0published 2026-09-09T03:58:15Z. Re-ran the on-ramp against the real registry at 2026-09-09T04:1xZ. ⭐ This is the reading criterion 4 said could only be taken after a release.Registry state — the fix reached users
reading before (17.3.0) now (17.4.0) dist-tags.latest17.3.0 17.4.0 declared @better-auth/core^1.7.21.7.2(exact)declared better-auth^1.7.21.7.2(exact)fresh install resolves core to 1.7.3 ← the break 1.7.2 the named import SyntaxError: … does not provide an export named 'createLocalAccountIssuer'links OK ( function function)create-objectstackand@objectstack/cliare both on17.4.0.The full first-run path, as a new user gets it
npx create-objectstack@latest smoke-app ✓ scaffolded npm install ✓ 447 packages in 37s, exit 0 ✓ @better-auth/core -> 1.7.2 in the fresh tree npm run build ✓ exit 0 — Build complete, dist/objectstack.json (2.1 KB) objectstack dev ✓ Server is ready after 12s — Plugins: 35 loadedAuthis in the loaded plugin list. ⛔ NoAuthPlugin failed to load, noCore service missing: auth, noSystem started with degraded capabilities, nono such table: sys_organization.Criterion 4 — the negative control, now measurable
original run 34084559243this run AuthPlugin failed to loadpresent absent boot diagnostics warnings 4 0 Auth + CRUD probes — never executed before this
These are the probes the canary could never reach, because the boot died first.
POST /api/v1/auth/sign-in/email HTTP 200 user admin@objectos.ai, token issued GET /api/v1/auth/get-session HTTP 200 session resolves to the same user POST /api/v1/data/smoke_app_note HTTP 201 id rfMZKzEzL6cEZf5v GET /api/v1/data/smoke_app_note HTTP 200 total 1, row present, tenant-stamped PATCH …/<id> HTTP 200 DELETE …/<id> HTTP 200⭐ Positive control that auth is genuinely enforcing, not merely present: the same list route without the cookie answers HTTP 401. A green read with no negative control would not have distinguished "auth works" from "auth is off".
⇒ All five of triage's acceptance criteria now hold. 1 and 2 were satisfied in source by #16634; 3 landed as PR #16794; 4 is measured above; 5 — #16630 and #16693 are untouched by this and keep their own cards.
⚠️ One error-level line remains, and it is #17027, not this cardERROR Insert operation failed {"object":"sys_oauth_resource", "error":{"message":"UNIQUE constraint failed: sys_oauth_resource.identifier …Exactly one, and the server still reaches
Server is readywith 35 plugins and green auth + CRUD above. ⭐ This run independently reproduces #17027 on PUBLISHED artifacts — previously it was only seen in CI — and confirms it is the vendor's documented race-safety no-op (@better-auth/oauth-provider: "one wins, the other catches the constraint error and treats it as a no-op") surfacing as an ERROR line. It is tracked there and does not qualify this card's verdict.维护者速读
⭐ 修好了,而且是在你刚发布的 17.4.0 上、按新用户的真实路径整条跑通验证的。
npx create-objectstack@latest→npm install→npm run build→ 起服务 → 登录成功、CRUD 增删改查全通。启动告警数从原来的 4 降到 0,AuthPlugin failed to load彻底消失。⭐ 关键的一条:登录探针第一次真正跑起来了 —— 以前每次都在启动就死了,根本走不到这一步。而且我加了阴性对照:不带 cookie 请求同一个接口返回 401,所以这不是"认证被关掉了"看起来像通过,是真的在拦。
⚠️ 还剩一行 ERROR,是 #17027(sys_oauth_resource唯一约束),不是这张卡的事:服务照常 ready、35 个插件、认证和 CRUD 全绿。这次跑还顺带在已发布产物上独立复现了 #17027(之前只在 CI 里见过),并确认它就是 vendor 文档写明的 race-safety no-op 被记成了 ERROR。⇒ 这张卡可以关了。
Generated by Claude Code
The weekly publish-smoke registry canary failed: a fresh
npx create-objectstack@latestproject no longer completes the first-run path against the npm registry — scaffold, npm install, npm run build, then auth + REST CRUD.Read the run log to see WHICH step failed, because the two have different owners:
getService(#4835) #4902/[finding] create-objectstack: non-blank remote templates fail firstnpm run buildon published 16.1.0 — fix is at HEAD, needs 17.0.0 release + canary verification #7644/All five published remote templates fail firstnpm run buildon GA create-objectstack@17.0.0 — templates still authorenable.trash/enable.mru, removed in the 16.x line #8677 class; the fix is in create-objectstack or the template it ships.Run log: https://github.com/objectstack-ai/objectstack/actions/runs/34084559243