Repository navigation
[Epic] v17 bug focus — Seat A: platform bugs (objectstack) #8667
Description
Activity
Sibling epic filed: #8668 — Seat B: console bugs (objectui repo +
repo:objectuicards here). The two seats partition the in-scope bug set: console-facing surface is B's, everything else objectstack-side is A's.
Generated by Claude Code
Ruling batch applied (maintainer 2026-08-14, verbatim: 「同意」 on the six-item list). Seat A queue changes:
- [finding] API keys carry no organization — under the isolated posture a minted key reads no org data at all (no leak, but the key surface is inert) #8287 joins the first batch — the cross-lane designation it was blocked on is resolved by assigning it to this theme seat as one integrated implementation of the already-ruled minimal v1. Now
pm:queue+target:v17. sys_setting's declared row identity is unenforced on everytenantandglobalrow —user_idis NULL there and SQL UNIQUE is NULL-distinct #8629 enters the workable set — Route 1 (runtime NULL-safe unique index atkernel:ready), refuse-to-migrate with an operator-facing duplicate list; serial behindsys_setting's unique key is installation-wide on a tenant-scoped object — but unlike the #8323 class it has a real argument for staying that way #8555.additionalTypesonMetadataPluginConfigis authorable, documented as THE way a plugin declares a metadata type, and has no reader — a plugin cannot declare a kind at all #8586 + meta-unknown-type-namespace: a/metatype name that is not a plural of anything still mints a namespace —PUT /meta/fieldz/xanswers 200 #8421 enter as a serial pair —additionalTypesonMetadataPluginConfigis authorable, documented as THE way a plugin declares a metadata type, and has no reader — a plugin cannot declare a kind at all #8586 ruled remove (ADR-0049); meta-unknown-type-namespace: a/metatype name that is not a plural of anything still mints a namespace —PUT /meta/fieldz/xanswers 200 #8421 then refuses/metatypes against the static registry (safe by construction once the plugin channel is gone).additionalTypesonMetadataPluginConfigis authorable, documented as THE way a plugin declares a metadata type, and has no reader — a plugin cannot declare a kind at all #8586 first.- hotcrm boundary settled: all nine platform mirrors were already fixed and closed by merged PRs; nothing mirrors into this seat today. hotcrm's GA close-out sweep ([GA close-out sweep] Apply the #1106 verdicts, close the verified-fixed rc-era platform cards, GA-retest the 8 likely-live ones hotcrm#1150) may nominate survivors from its group-4 retests for
target:v17here — nominations only, maintainer approves each.
First batch now: #8193 · #8617 · #8262 · #8154 · #7987 · #8287, then #8629 / #8586→#8421 as serials clear.
Generated by Claude Code
- [finding] API keys carry no organization — under the isolated posture a minted key reads no org data at all (no leak, but the key surface is inert) #8287 joins the first batch — the cross-lane designation it was blocked on is resolved by assigning it to this theme seat as one integrated implementation of the already-ruled minimal v1. Now
Decision-box ruling batch applied (maintainer 2026-08-14, verbatim: 「同意你的建议」 on the eight-item list). Seat A queue changes:
- Migration story for stored cleartext datasource credentials: operator-initiated re-homing into sys_secret (blocked by the managed-schemaMode refusal) #8155 (cleartext datasource credential migration, shape (b)) — joins the workable set,
target:v17. Coupling: [security] GET /api/v1/meta/datasources still serves stored cleartext credentials — the metadata read path has no per-type redaction hook #8154 must not strip_diagnostics. sys_permission_set.activeandsys_position.activeare unenforced too — both Deactivate dialogs promise access stops, and it does not #8613 (enforceactiveon sys_permission_set / sys_position, full coverage) — joins the workable set,target:v17.- The 2026-08-13 max_nodes ruling's "loud warning" clause has no owner:
os servecalls the multi-node gate zero-arg, so a partial cap is silent even once the gate can express it #8504 (max_nodes loud advisory warning) — joins the workable set,target:v17; its mechanism sibling A licensedmax_nodescap still cannot be enforced by any replica: the cluster has no membership view and no slot claim, so a count-carrying gate verdict stays advisory #8501 is parkedpm:on-holdwith a named restart condition. - [Decision]
sys_*objects silently default to PUBLIC row visibility — should the platform's own objects keep an unstated default at all, and isisSystemeven the right predicate? #8641 — probe-first: an S-size live probe of the sys_* public default runs before any classification work;target:v17only if the probe is red. - decision(spec): which schema does an SDUI dashboard COMPONENT node validate against? DashboardSchema rejects every objectui catalog example on three independent axes #8593 closed by ruling (option 1; objectui#4600 unblocked). [finding] ADR-0002's "already discarded in v3.4's ADR-0001" points at a document this repo never contained — the number it cites held an unrelated decision #7963 queued as a one-sentence ADR-class docs fix. [finding] 仓内存在 5 个独立的过滤器→谓词编译器,每次语义裁决成本 ×5 —— 值得立「谓词编译收敛」调查程序(#5298 成本清单副产品) #5930 parked with restart = this theme's
target:v17set reaching zero (the investigation is the theme's approved successor).
Decision box after this batch: 1 item — #8446, which is a personal maintainer action (file the pre-drafted better-auth upstream issue), not a seat task.
Updated first batch: #8193 · #8617 · #8262 · #8154+#8155 (coupled) · #7987 · #8287 · #8613 · #8504, with #8629 / #8586→#8421 / #8641-probe as serials and smalls behind them.
Generated by Claude Code
- Migration story for stored cleartext datasource credentials: operator-initiated re-homing into sys_secret (blocked by the managed-schemaMode refusal) #8155 (cleartext datasource credential migration, shape (b)) — joins the workable set,
Routing update (maintainer 2026-08-14, verbatim: 「spec 车道的项目经理上班了,相关任务还是由他处理。」): the two
domain:speccards leave this seat's ladder — #8586 and #8641 route to the live spec lane seat (#6017, notified). Consequence for this seat: #8421's serial start condition is now cross-seat — it begins after the spec seat lands #8586. First batch unchanged: #8193 · #8617 · #8262 · #8154+#8155 · #7987 · #8287 · #8613 · #8504; remaining serials here: #8629 (after #8555), #8421 (after spec's #8586).
Generated by Claude Code
Charter amendment (maintainer 2026-08-14, verbatim, untranslated): 「spec 车道的项目经理上班了,spec任务还是由他处理。」「其他人不得接手」 — standing exclusivity rule, stronger than the routing note above: ⛔ every
domain:spectask is the spec lane seat's (#6017) alone; this seat must never claim, dispatch, or take over a spec card under any circumstances — the scope carve-out for live lane seats (devx, spec) is now a hard prohibition for spec, not a courtesy. Cross-seat serials remain the one sanctioned interaction shape: wait for the spec seat's merges (e.g. #8421 after #8586), never do their work.
Generated by Claude Code
Nomination — three v17 authorization/security candidates, measured on 17.0.0 GA
Nominating only; no labels applied, and the first-batch list above is untouched. Per this epic: "The PM nominates second-batch candidates with a short list on this epic; the maintainer approves by labeling".
This is the boundary note in this card's own Out of scope section coming due — "hotcrm's four P0s (e.g. #703, wildcard grant union) accuse platform defects; whether to mirror their platform-side verification into this theme is an open maintainer call — until then, v17's authorization surface has no assigned verifier." Under maintainer ruling 2026-08-14 (verbatim 「同意」) the hotcrm side ran that verification: five security/authorization cards re-probed on GA under real Bearer tokens (objectstack-ai/hotcrm#1152). Two closed green; the three below survived and are filed here as platform cards. Nothing else from hotcrm enters this theme.
candidate class state on 17.0.0 GA #8681 security org-admin sets ship object_permissions['*'].allowExport = true; an app cannot deny the export axis to an org admin, and the sets answernot_overridable#8679 bug controlled_by_parentchildren still refuse an RLS-widened master — PR #6909 fixed the by-id write path only#8682 bug undeclared fields still reach the driver: hooks run, an auto-number is consumed, and the full INSERT with values is logged at ERROR Why each is worth a slot
#8681 is the one I would rank first. It is the same shape as #703 — a platform wildcard grant that erases an app's explicit-allow declaration — on the one axis that #5491 / PR #6684 did not sweep. It is measured, not inferred: a wildcard export grant confers export on a principal with no admin status, and a more specific per-object
falsebeats the wildcard, so a supported opt-out shape already exists and is simply out of an app's reach. Bulk egress with no app-side denial is a security posture question, not a bug-fix question, which is why it is nominated rather than queued.#8679 is a partial-fix follow-up rather than a new defect: #5493 closed via merged PR #6909, and the rc.2 symptom really is gone. What survives is the derived-write path, where
security/explainand the master-editability check now return opposite verdicts for the same principal, record and operation. Cheap to bound because the disagreement is between two named call sites.#8682 is the lowest severity of the three, and half of it has already been fixed upstream (the false
[REST] Unhandled errorlabel is gone). It is nominated for the surviving half: a mistyped field name in a client request writes the whole row's values to disk at ERROR level, confirmed with planted canaries.Not nominated (closed green on GA, recorded for the ledger)
- hotcrm#703 — the
member_defaultwildcard union. Closed.member_default's*wildcard object grant (C/R/E) union-merges into every org member — app-side explicit-allow object gates are erased on three axes #5491 / PR fix(plugin-security): enforce both declared write-wideners; the platform baseline becomes explicit-allow (#5492, #5491) #6684 holds: 90 create cells, 90 read cells and 90 edit cells across 5 principals x 18 objects, zero declared-deny cell allowed on any axis. Verified falsifiable — re-injecting the rc.2 wildcard shape at runtime restored the exact rc.2 symptom (201s, andgranted by [set]insecurity/explain), and removing it restored the refusals. - hotcrm#705 —
modifyAllRecordsand edit-levelsys_record_share. Closed. Both mechanisms now widen writes; Row-level write gate consults neithermodifyAllRecordsnorsys_record_share.access_level— both declared write-widening mechanisms are inert #5492 / PR fix(plugin-security): enforce both declared write-wideners; the platform baseline becomes explicit-allow (#5492, #5491) #6684 holds.
Generated by Claude Code
Generated by Claude Code
- hotcrm#703 — the
Nomination — 4 platform cards mirrored from the hotcrm GA close-out sweep
Posted by the hotcrm PM seat, session
session_01XAK3brMLjd4ykF4QAhFnuo, from hotcrm#1153 (sub-issue of hotcrm#1150). These are nominations, not labels — nothing here carriestarget:v17and the first-batch list above is untouched, per this epic's "the PM nominates … the maintainer approves by labeling" and hotcrm#1150's "Seat A decides nothing".This is also the boundary case this epic's Out of scope section flagged: "whether to mirror their platform-side verification into this theme is an open maintainer call." Each card below is a platform defect re-measured live on 17.0.0 GA, not an rc-era report carried forward — every one of the six cards in that sweep was re-probed and two of them died on contact and were closed, so this list is what survived measurement.
# card one-line evidence class #8686 Seed loader writes untenanted rows while REST stamps an org — two autonumber scopes on one single-tenant install, duplicate business identifiers, silent live REST + sequence-table + index DDL #8687 Unknown top-level stack key named but not rejected — and the diagnostic is not a warning, so --strictcannot catch itschema parse + controlled validateruns, 88-vs-88 warning diff#8688 Missing required master-detail parent answers 422 with no fields[]; the same field present-but-unresolvable answers 400 withfields[](#7474 residual)six-branch REST comparison, one server/session #8689 A record-change flow's start condition is not evaluated on the re-entrant dispatch its own write causes — the loop-breaker is the sole guard, and says so two flows, record-id-filtered engine WARNs, guard terms read back Notes that may affect ranking
- Seed loader writes untenanted rows while the REST path stamps an organization — one single-tenant install runs two autonumber scopes and mints duplicate business identifiers, silently (17.0.0 GA) #8686 is the one with silent data consequences: a
uniquerecord-number field carrying duplicates that no constraint catches, because the two copies sit in different partitions of the uniqueness index. It is the residual of Autonumber counter neither syncs to MAX(existing) per tenant nor re-checks on collision — warm-DB creates 409 in bursts, each failure burning a number (25 retries observed) #5495 (closed, PR fix(driver-sql): re-seed a stale autonumber counter instead of burning a number per failed create (#5495) #6932) — that card's burn-on-failure half is confirmed fixed in the same run and recorded as such, so this is genuinely new surface rather than a reopen. - A missing required master-detail parent still answers 422 MISSING_REQUIRED_FIELD with no
fields[]and a[Security]message — while the same field, present-but-unresolvable, answers 400 VALIDATION_FAILED withfields[](#7474 residual, 17.0.0 GA) #8688 is the residual ofassertControlledByParentWriteanswers a metadata defect and a missing row with the same403 PERMISSION_DENIED"requires edit access to its master record" #7474 (closed). The 403 it was filed on is gone; what remains is the envelope shape, and the platform already emits the wanted envelope for the adjacent case on the same field, so the fix has a working reference implementation a few lines away. - A record-change flow's start condition is not evaluated on the re-entrant dispatch its own write causes — the loop-breaker is the only thing stopping the loop, and it says so itself (17.0.0 GA) #8689 has no data corruption today — the breaker holds. Its argument is that the authored guard is not what holds, so the safety margin is one narrow mechanism (
flowName::recordId, while still running) that no author knows they depend on. - An unknown top-level stack key is named but still not rejected — and the diagnostic is not a warning, so
objectstack validate --strictcannot catch it either (17.0.0 GA) #8687 is the cheapest: counting the existing drop diagnostic as a warning would make--strictfail on it and close the practical gap without the breaking.strict()change.
One adjacent finding, filed but deliberately NOT nominated
#8690 — an unparseable date comparand on a datetime filter returns
HTTP 200with zero rows and no diagnostic, while an unknown{placeholder}on the same request is rejected400 FILTER_TOKEN_UNKNOWN. Found while probing hotcrm#520 to closure. Leaving it to ordinary triage rather than pushing it into this batch, but flagging it here because it is the same silent-empty-result family that cost hotcrm three weeks on #520 and it is reachable by any caller holding a declared preset name.Two cards from the same sweep were CLOSED, not nominated
Recorded so the account-book stays honest about what measurement actually produced: hotcrm#520 (datetime window filtering) and hotcrm#779 (
ctx.previousempty onmulti: true) both failed to reproduce on GA and were closed with their readings. #779's close specifically confirms #5574 → PR #6697 landed correctly, including that the new 10000-row per-row dispatch ceiling refuses loudly and writes nothing rather than masking the old silent no-op.
Generated by Claude Code
Generated by Claude Code
- Seed loader writes untenanted rows while the REST path stamps an organization — one single-tenant install runs two autonumber scopes and mints duplicate business identifiers, silently (17.0.0 GA) #8686 is the one with silent data consequences: a
Nomination — 1 platform card for
target:v17, from the hotcrm GA close-out browser sweepNomination only: no labels applied, no change to the first-batch list. Filed from objectstack-ai/hotcrm#1154 (parent hotcrm#1150).
#8691 —
record:reference_railhas noComponentPropsMaprow, so an entryfilteris accepted everywhere and honoured nowhereDownstream: hotcrm#986. This is a
packages/specfix, which is why it comes to this desk rather than Seat B — nothing in the console renderer has to change.Measured on
@objectstack/spec17.0.0 GA:ComponentPropsMaphas 37 component keys, sixrecord:*among them, and norecord:reference_rail. With no row,PageComponent.propertiesstays an open bag and nothing parses a rail entry on any path.Reverse verification on a real app, direction fixed before running — planted
filter: [{ field:'status', op:'neq', value:'completed' }]on a rail entry whose object has 3 related rows, 2 of them notcompleted:stage result tsc --noEmitexit 0 objectstack validatepassed — reference_railappears 0 times in outputobjectstack buildexit 0 — 0 times shipped artifact filter present verbatim in dist/objectstack.jsonrendered rail badge unchanged at 3, the completedrow still listedThe same build run emits loud
component-props-unknown-key/component-props-invalidwarnings forrecord:related_list,record:activityandpage:accordionin the same file — the rail is silent purely because it is undeclared. Control:ComponentPropsMap['record:related_list'].safeParsewith a bogus key does reject.Why v17. This is the exact failure shape #4001 was closed to eliminate, still open on this component: metadata that typechecks, validates, builds, publishes and does nothing, while the source now claims it filters. It is the class of error an AI metadata author produces most readily and a human reviewer catches least — the diff looks correct and every gate is green. The fix tightens an existing shape rather than expanding the authorization surface, so it needs no ruling on business pull and no new capability: one strict row describing what the renderer already reads, turning a silent no-op into a loud publish-time rejection.
The downstream card's other two gaps (rail title cannot reach
pluralLabel; title is an untranslatable literal) are console/objectui surface and genuine capability expansion — they are explicitly excluded from #8691 and are not nominated anywhere, because the only consumer found repo-wide is a single rail on one detail page and the pull question is unanswered. Recommend they stay frozen until the maintainer rules.Card is unassigned and was duplicate-checked (nearest hit: #1894, closed).
Two console cards from the same sweep — objectui#4644, objectui#4645 — went to #8668 instead, since this epic's Scope section routes
repo:objectuiwork to Seat B. Flagging that here because hotcrm#1154 named #8667 as the nomination target for all survivors; three of its five cards were console surface, so the instruction and the epic boundaries disagreed. Resolved in favour of the epic boundaries.
Generated by Claude Code
Theme charter for the post-v17 priority regime. Filed by the (former) skills PM seat, session
session_018WuTtyckQa1VcXwgd52JpN, on maintainer instruction.Authority (maintainer, 2026-08-14, verbatim, untranslated)
Scope
All open
bug-labeled cards in objectstack (37 at filing), every domain — EXCEPT cards already in flight under the two live lane seats:domain:devx(#6023) anddomain:spec(#6017). Console-facing cards (repo:objectui) belong to the sibling theme, Seat B (see the epic filed immediately after this one; the two cards cross-reference in the comments).Workability rule (the default flip): a card is workable under this theme only when it carries
target:v17. Everything else stays frozen stock — no lane-clearing. The PM nominates second-batch candidates with a short list on this epic; the maintainer approves by labeling (or one-word ruling), and only then do they enter the queue.First batch (workable now or pending one maintainer ruling)
oidcConfig.mapping.id, which@better-auth/sso@1.7.0-rc.2rejects as an unrecognized key #8193 — OIDC SSO registration broken end-to-end (pm:blocking)target:v17)context, leaving a dangling value_enc and an unreadable setting #8262 — reapRotatedSecret deletes the in-force ciphertext (target:v17)target:v17)sys_accountstores live third-party OAuth access/refresh/id tokens as plain columns, and the object is API-readable #7987 — sys_account stores live OAuth tokens in plain columns (security,target:v17)P0 rulings pending on the maintainer's desk (fix-in-17.x / defer-v18 / void): #8500, #8282, #8096, #8270 (those four are Seat B surface), #8287. Decision-gated bugs pending one-sentence rulings: #8629, #8586, #8421.
Before dispatching anything: orphan re-verification
Former lane PMs stood down without closing out. Verify the true state (PR? merged? labels?) of each and either close out or re-dispatch under this theme:
domain:identityledger named sharing rules: thebusiness_unitrecipient expands the whole SUBTREE, but the spec declares it as exactly one unit (no subtree) #7807, A successful/auth/change-passwordover a BEARER token never clearsmust_change_password— the caller is permanently locked out of every protected route with a 200 telling them it worked #8049, [finding] The bulk AST write path passesopCtx.operationraw, sopurge/transfer/restorederive no row scope whileupdate/deletenow do (#7665 asymmetry) #7809 as dev-in-flight (2026-08-12) — none appear in the currenttarget:v17listing, so they may have landed or lost their labelsdomain:driversledger named finding: after the #7598 Q1=B ruling, a read scope with a driver-refused field reference answers 400 from the driver — which cuts across #5367's attribution argument on that one path #7929 as in flightdomain:cliledger named 【缺陷】数据导出(CSV/XLSX)日期时间列硬编码按 UTC 渲染,与界面时区不一致(@objectstack/rest export-format.ts formatDate) #8373 (draft PR open) and RuntimeConfigPlugin's features.installLocal is still a hand-maintained knob — the same declared-is-not-enforced shape #8356 just removed from features.marketplace #8388 (ACCEPT awaiting landing)Operating rules
priority:p0>pm:blocking>security> age..claude/skills/**,skills/**,.claude/agents/os-dev.md, orAGENTS.mdis ADR-class — draft + human merge, per standing rules.needs-user-decisionor the round report.Out of scope (by ruling)
hotcrmandcloudrepos. Boundary note for the maintainer: hotcrm's four P0s (e.g. #703, wildcard grant union) accuse platform defects; whether to mirror their platform-side verification into this theme is an open maintainer call — until then, v17's authorization surface has no assigned verifier.Done means
Every in-scope
target:v17bug is closed (fixed, or ruled defer/void with the ruling recorded); the five P0s all carry an explicit maintainer disposition.