Skip to content

Commit f1b5758

Browse files
Merge branch 'main' into claude/issue-25742-liveness-flows-screens-anchor
2 parents 138ec32 + 5f5f0b4 commit f1b5758

38 files changed

Lines changed: 2643 additions & 150 deletions
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@objectstack/objectql': patch
3+
---
4+
5+
fix(objectql): a free-text `search` resolves only over the fields the caller may query
6+
7+
Clause-②: yes (widening)
8+
Metadata-protocol: none
9+
10+
The server-resolved search set used to include fields the caller cannot read, so the field-read predicate guard refused the whole expanded `$or` with 403. On `sys_user`, `role`, `ban_reason` and `last_login_ip` broke every user and owner picker for non-admin members as soon as they typed. The engine now asks the registered security service's `getQueryableFields` (the complement of what the guard refuses) and withholds every other field from the resolved set, on `find`, `findOne`, `count` and `aggregate`. The guard is unchanged: an explicit `filter`, or a `searchFields` naming a hidden field, is still refused with 403. A search whose declared fields are all hidden from the caller answers the existing `400 INVALID_FIELD` empty-search-set refusal, never every row.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
'@objectstack/skills': patch
3+
---
4+
5+
docs(skills): the automation skill's inbound-hook table names `config.secretRef`, the form a package ships instead of a literal secret
6+
7+
Clause-②: no
8+
9+
Metadata-protocol: none
10+
11+
The `objectstack-automation` skill's start-node table said an `api` flow needs a non-blank literal `secret`, or the flow is refused at registration. An `api` flow's start node may now name its secret instead, with `secretRef: 'NAME'`: the deployment fills that name (an environment variable in the open tier, never `OS_*`), and the engine reads it at every post, answering `503` while the name is unfilled. The row now says either one is required, and that a package ships `secretRef` and never commits a literal. The signature line names the `x-objectstack-signature` header the row used to carry.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
'@objectstack/mcp': patch
3+
'@objectstack/runtime': patch
4+
---
5+
6+
fix(mcp,runtime)!: the stateless `/api/v1/mcp` surface answers `GET` and `DELETE` with `405` and `Allow: POST`, so an MCP client stops re-opening a GET stream that ends at once
7+
8+
Clause-②: yes (narrowing)
9+
Metadata-protocol: none
10+
11+
<!-- adr-0087: not-required (no-migration-prescription) A transport verb answer on the MCP HTTP surface: no key of any metadata schema is removed, renamed or re-shaped, no export, type or error code is removed or renamed, and the 405 body is the MCP SDK transport's own. There is nothing for `objectstack migrate meta` to rewrite and no tombstone. -->
12+
13+
**BREAKING** accept-set narrowing at the MCP HTTP transport (`MCPServerRuntime.handleHttpRequest`, `@objectstack/mcp`), and on the standalone server's `/api/v1/mcp` route (`createDispatcherPlugin`, `@objectstack/runtime`).
14+
15+
- **Before.** The transport is stateless (no session id) and closes its per-request server when the request ends. A `GET` still reached the SDK's stream handler, which answered `200 text/event-stream` and then lost the stream when the server closed. An MCP client reads a GET stream that ends as a dropped connection and opens another one: claude-code re-opened it 2–3 times a second for as long as a session stayed connected. A `DELETE` answered `200` and ended nothing, because no session exists. Every other verb answered `405` with `Allow: GET, POST, DELETE`.
16+
- **Now.** Every verb but `POST` that reaches the transport (`OPTIONS` with CORS off; with CORS on the CORS middleware's `204` answers first on both doors) answers `405` with `Allow: POST` and the JSON-RPC body `{"jsonrpc":"2.0","error":{"code":-32000,"message":"Method not allowed."},"id":null}`, before a server is built. This is the Streamable HTTP transport's answer for a server that offers no GET stream and does not end sessions. The MCP SDK client treats a `405` on GET as "no stream offered" and does not retry it.
17+
- **The standalone server.** `createDispatcherPlugin` mounts `/api/v1/mcp` for `GET`, `POST` and `DELETE`, and now also declares it a path whose domain decides every verb (the declaration `/mcp/skill` and `/keys` already carry). Before, a `PUT`, a `PATCH` or an `OPTIONS` with CORS off matched no route there and the HTTP adapter answered it itself: `405` with `Allow: DELETE, GET, HEAD, POST` and a `METHOD_NOT_ALLOWED` envelope, to an anonymous caller too. Now those verbs reach the dispatcher like the mounted ones: an anonymous caller gets `401`, a signed-in one the transport's `405` with `Allow: POST`. A `createHonoApp` host already handed every verb to the dispatcher, so both doors now answer every verb alike.
18+
- **Unchanged.** `POST` (JSON-RPC: `initialize`, `tools/list`, `tools/call`, …) answers exactly as before. An anonymous caller is refused `401` before any verb answer, on every verb and on both doors.
19+
- **Who sees it.** A client that opens the GET stream on `/api/v1/mcp` now gets `405` instead of a `200` stream that ends at once. Nothing was ever sent on that stream. On the standalone server, an anonymous `PUT`, `PATCH` or `OPTIONS` (CORS off; with CORS on the CORS middleware's `204` answers `OPTIONS` first on both doors) on `/api/v1/mcp` now gets `401` instead of `405`.
20+
21+
**The remedy.** None needed for an MCP client: it stops opening the stream. A probe or health check that read `GET /api/v1/mcp` as `200` should send a `POST initialize` instead.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
'@objectstack/cli': patch
3+
---
4+
5+
feat: the Console document is served with a nonce-based content-security-policy
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
Every HTML answer under `/_console/` (`os serve`, and so `os dev`, `os start` and the Docker image, which all run it) now carries a `content-security-policy` header. Each response draws a fresh nonce, and every `<script>` the Console build ships, plus the server's own react-pages disable script, is stamped with it. Other scripts may load only from the server's own origin.
11+
12+
The policy, and why each part is there:
13+
14+
- `script-src 'self' 'nonce-…' 'wasm-unsafe-eval'`. WebAssembly compilation is for the AI chat's code highlighter. `'unsafe-eval'` is added only while the `kind:'react'` page tier is on (ADR-0081, on unless `OS_PAGE_REACT=off`), because that runtime evaluates page source.
15+
- `style-src 'self' 'unsafe-inline'`, for inline styles written by the UI libraries at run time.
16+
- `img-src 'self' data: blob: https:`, for branding, avatars and image fields hosted elsewhere.
17+
- `connect-src 'self'`, plus the default map style's host, plus the error-reporting endpoint's origin when the runtime serves a DSN.
18+
- `object-src 'none'`, `base-uri 'self'`, and `frame-ancestors 'self'`. The public form page (`/_console/f/<slug>`) is the exception to `frame-ancestors`, because authors embed it on other sites.
19+
20+
What an operator may notice:
21+
22+
- **A map view whose `mapStyle` names another host** is refused that host until the operator lists it. Name it in the new `OS_CONSOLE_CSP_CONNECT_SRC`, a space-separated list of sources such as `https://tiles.example.com`. A malformed entry stops the server at boot with a message naming it.
23+
- **Framing the Console from another origin is refused.** The public form page is the exception.
24+
- **The Studio's code editor** loads its editor core from a public CDN, which the policy does not list. It shows its built-in plain-text editor instead.

‎.claude/skills/pm-dispatch/SKILL.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ PM 的工作是循环:选卡 → 认领 → 派发 → 收集 → 复核 → 报
111111
| `pm:blocking` | 有 open 下游依赖者(自 `Blocked-by:` 索引推导的缓存,⛔ 不手工挂);进选择全序 |
112112
| `pm:retriage` | 向分诊提问(改判、跨域 PR 指定车道、改路由、拆卡、裁 dev 报告留下的分叉),定车道与改路由限未派发卡,异议评论写明所求;与现行 `pm:*` 并存、⛔ 不摘原标;带本标签的 `pm:queue` 卡跳过派发 |
113113
| `finding` | 立卡三类内待首次定级,定级即离标;三类外关 not planned;不占队列不进收件箱 |
114-
| `tooling` | 修复落在门禁/脚本/workflow/技能/席位协议/PM 工具面而非产品包;分诊首触打,与 `domain:*` 同笔;三具名读者 = 候选查询排除、首触即关、普查半态行 |
114+
| `tooling` | 修复落在门禁/脚本/workflow/技能/席位协议/PM 工具面而非产品包;分诊首触打,与 `domain:*` 同笔;四具名读者 = 候选查询排除、每轮派发 ≤10%、首触即关、普查半态行 |
115115
| `target:<major>` | 发版阻塞:每个 backlog 恰好一个生产者 |
116116
| `pm:epic`(父单或 sub-issue) | 已由 epic PM 保留;其它 PM 永不取;⛔ 永不与 `pm:queue` 同挂 |
117117
| `pm:seat` | 座位登记贴:协议载体,不是待分诊的工作 |

‎.claude/skills/pm-dispatch/references/cross-repo-coordination.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
分诊席每次 fire 路由与查重前读本文;执行席跨仓认领、派发或转移时读本文。
44

55
- 产品依赖方向固定:`objectstack`(后端,`packages/spec` 是唯一契约)→ `objectui`(前端)与 `cloud`。
6-
- objectui 构建产物经 `pnpm objectui:refresh` 回流。
76
- 多车道仓 `objectstack`、`objectui`:中央分诊是 `domain:*`/type/定级的唯一生产者。
87
- 单车道仓 `cloud`、`objectos`、`hotcrm`、`www.objectos.ai`;未来新仓默认此类。
98
- 单车道仓 `repo:*` 席自理机械三务,⛔ 不产 `domain:*`;决策卡入本仓收件箱,不落 objectstack。
@@ -26,8 +25,9 @@
2625
- 缝卡收窄为真协调卡:留 objectstack 带 `repo:*`,正文点名读者(哪个座位、哪一步)。
2726
- 决策卡留在立卡仓,总监席扫全部仓 `needs-user-decision` 呈批;在飞卡 ⛔ 不中途转仓。
2827
- 规则 2:跨层功能点或 objectui 消费的 `Seam:` 卡恒由分诊立父单 + 逐层子单,spec/后端先行。
28+
- `main` 有 `ui/` 起,新 spec 键不再先行、取代上句次序:与首个读者同 PR,hotcrm 读者同合并批。
2929
- 下游带 `Blocked-by: <owner/repo>#<n>`;`Blocked-by` 未关闭/未合并的不派发,对 GitHub 现验。
30-
- 被链接或同父的两单永不同批。
30+
- 被链接或同父的两单永不同批;`ui/` 起的新键与首个读者除外,⛔ `planned` 行不单独进 main。
3131
- pin 滞后是盲区:本仓 pin 是否已覆盖该 commit 是第二读数,派发前用 REST `compare` 核祖先。
3232
- 本地 `merge-base` 在浅检出上给假非祖先;未覆盖 ⇒ 派发令要求 PR 正文留档分叉窗口。
3333
- ⛔ pin bump 不做 rider:走专用 bump 脚本连带 override 与 lockfile。

‎.claude/skills/pm-dispatch/references/execution-duties.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
- 整车道一次读全,本地求交:`list_issues` 带 `labels: [domain:X]` + 最小字段拿回全车道 open 集。
88
- 候选 = open、未 assign、无 `needs-user-decision`、无 `pm:retriage`;⛔ 排除三门皆无的 `tooling` 卡。
9+
- `tooling` 卡至多占一轮派发的 10%,溢出留积压、⛔ 不入 `pm:queue`;⛔ 无门禁无脚本强制。
910
- 无分诊审计评论的卡不是候选,预贴 `pm:queue` 视同无;例外一的 sub-issue 承父卡首触。
1011
- 已排队父单的 open sub-issue 自动是候选,`pm:epic` 父单的子树除外。
1112
- 每张候选读全文 + 全部评论,写派发词前做决策复读:评论读到最后一页。
@@ -56,7 +57,6 @@
5657

5758
- 归属 = session ID,⛔ 不认作者字段;`Account:` 派生自 assignee,不等即半态、持卡席下笔补正。
5859
- 卡 assignee 归 PM,dev 恒不写;PR assignee = 卡的,接管 ② 同笔换;读者 `is:pr is:open assignee:LOGIN`。
59-
- dev `pr_create` 带 `assignees: [LOGIN]`,同笔指派;席位自有 PR 指派自己。
6060
- 部分落地(PR 带 `Refs #N (item k)`,⛔ 不 `Fixes`)即释放:合入同笔回 `pm:queue` + 清 assignee。
6161
- 同笔 `Release:` 行点名已落项与余项去向;余项需换道/拆分加 `pm:retriage`,自队列重新认领。
6262
- 派发前按序执行原子对:① Assign @me,并把 `pm:dispatched` 与摘 `pm:queue` 放进同一次标签写入。
@@ -93,10 +93,10 @@
9393
- 下限档给机械卡(正确性由门禁农场机械判定)。
9494
- 默认判断档给 M/L、裁决实施与任何带设计判断的卡;拿不准就升一档。
9595
- 上限 = 契约复审档(`CONTRACT_REVIEW_TIER`),给最重协议/流程/编排卡,按卡取用非新默认。
96-
- 强制条款①:凡改协议语义面的卡一律契约复审档。
96+
- 强制条款①:凡改协议语义面或 `docs/adr/**` 的卡一律契约复审档;后者 effort 下限 `xhigh`。
9797
- 协议语义面 = 本 `SKILL.md`、决策框架拷贝所在文件、`.claude/agents/os-dev.md` 与 `skills/**`。
9898
- 仅 `references/**` 面、或治理面上一行级机械文本改动的卡,降为默认判断档施工。
99-
- 发布的 `skills/**` 整根随 `npx skills add` 发运,⛔ 无一行级豁免,逐行判机械不作数。
99+
- `skills/**`(随 `npx skills add` 发运)与 `docs/adr/**` ⛔ 无一行级豁免,逐行判机械不作数。
100100
- 纯机械一行 PM 酌定可至下限档;降档施工的补偿控制 = 复核席跑契约复审档。
101101
- 降档施工只经契约复审档复核到达维护者,⛔ 不新增标签不新增链。
102102
- 强制条款②:放宽接受集或扩大公开面的卡默认判断档施工;命中即 spec 车道的活。

‎.claude/skills/pm-dispatch/references/filing-gate.md‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# 立卡门与定级判据
22

3-
见 triage-duties.md 与 reading-discipline.md 的指针行。
4-
53
## 立卡门
64

75
> 出处,维护者 2026-09-21 逐字不译:刚才 os-sam 又被封号了,也是因为分诊批量处理issue的时候,所以现在 issue 太多对于车队是负担。 19546 我希望在创建issue 的环节就卡死,没必要的issue就不要创建。
@@ -16,6 +14,7 @@
1614
- 三种例外照立,要点首条「先测可达性」:可能泄露数据;发版固化的错误文字;维护者直派。
1715
- ② 只有维护者能做的决定,落卡即带「维护者速读」与四棱块。
1816
- ③ 维护者直派的任务,正文引其原话;④ 协调节点:跨仓/跨层父单与它的逐层子单。
17+
- 增改 pm 规则的卡只在维护者点名时立(归 ③,正文引点名原话);⛔ 席位自提不立。
1918
- ⛔ 不是卡:席位自己的失误、协议观察与「记住这条」,它们进座位贴或收班简报。
2019
- 「搭下个碰 X 的 PR」不算 `carrier:`;已落地工作欠的后续照立卡,⛔ 不按「不是卡」压下。
2120
- ⛔ 不是卡:丢卡重建(除非自身即 ①–④)、sweep 每 fire 重导的 pin/bump/卫生提醒。
@@ -31,7 +30,7 @@
3130
- 补不齐(四类皆非)者才因缺件首触即关 not_planned,一行点名所缺。
3231
- 「动手的读者」与 Acceptance notes 同一问:说得出具体 PR 或人 ⇒ 写进去,说不出 ⇒ 不立卡。
3332
- 说不出的形态:`.changeset/*`、无人在改的文档页、生成物、已扫完的批次,兜底不成立。
34-
- 配额:一席每 fire 至多三张,超出折清单卡或座位贴;QA/走查逐缺陷立不限张数,守批量间隔。
33+
- 配额:每 fire 不限张数,逐缺陷各立一张、各过本门;折清单卡可选、不强制;守批量写间隔。
3534
- 分诊席的存量清理仍走维护者确认的十张一组、只备下一组,⛔ 不因本门改批量。
3635
- 读到 `User` ⇒ 记座位贴、本 fire ⛔ 不立新卡;认领仍靠 assignee,署名仍是文本的 session ID。
3736

‎.claude/skills/pm-dispatch/references/lanes/ui.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
## 常设承诺
1919

20-
- 构建产物经 `pnpm objectui:refresh` 回流,见 cross-repo-coordination.md。
20+
- 构建产物经 `pnpm objectui:refresh` 回流,见 AGENTS.md。
2121
- 回流后的 console pin bump 是 objectstack 的单张卡,⛔ 永不做本仓 PR 的 rider。
2222
- `scripts/pm/**` 单写手恒在 objectstack 侧 ⇒ 本席的工具需求走上游卡带 `Blocked-by:` 回链。
2323
- 本仓标签/assignee 写走 objectstack `label-write.mjs --repo`,⛔ 不 MCP `issue_write`;被拒转有通道席。

‎.claude/skills/pm-dispatch/references/seat-lifecycle.md‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@
4242
- 收班 = 状态 flush + 在飞显式安置,不是在飞归零;派发口径失效,简报 ⛔ 不列作继承裁决。
4343
- 离任留守只写简报点名的项,⛔ 不读队列、不新派发、不碰未点名卡。
4444
- 换班报告默认零建议,只收三类:原则错/缺、可机械化项、平台事实变化。
45-
- 原则错/缺 → skills 席专题;可机械化项 → 门禁/脚本卡,⛔ 不是散文。
45+
- 原则错/缺 → 只进简报,维护者点名才立卡;可机械化项 → 门禁/脚本卡,⛔ 不是散文。
4646
- 平台事实变化 → references 事实表改一行。
47-
- 三类以 `finding` 入 skills 车道,首触归分诊席;三类之外默认关 not planned。
47+
- 后两类以 `finding` 入 skills 车道,首触归分诊席;三类之外默认关 not planned。
4848
- 接管/移交 = 改正文 + 审计评论(只作审计);收尾清单等细则见 `references/seat-post-protocol.md`。
4949
- epic 委托不入座位贴体系;新 `packages/spec` 工作恒归 spec 座位。
5050

@@ -68,7 +68,8 @@
6868

6969
- 每轮向维护者打中文轮次报告(chat 通道):issue → 判决 → PR 链接 → 备注的表。
7070
- 项目席轮报 = 卡线程清单,⛔ 不逐轮发聊天表;五项健康指标进总监席的每日摘要。
71-
- 报告加升级项、呈裁清单、awaiting a human merge 项、逐 PR 熔断命中项(无则 none)。
71+
- 报告加升级项、呈裁清单、逐 PR 熔断命中项(无则 none),与已落 PR 48h 内开出的跟进 PR 数。
72+
- 与产品提交占比:已合提交不触 `.claude/` `AGENTS.md` `scripts/pm` 门禁脚本 `.github/workflows` 者。
7273
- 报告含 `UNRECOGNISED` 行:对本轮门禁日志 grep `UNRECOGNISED` 逐行照录,`NOT APPLICABLE` 行也在内。
7374
- 健康指标五个:可派发库存(open `pm:queue` 未认领及趋势);决策箱(待维护者数)。
7475
- 决策箱指标还要点名带开放下游依赖的决策卡,从 `Blocked-by:` 反向索引现算。

0 commit comments

Comments
 (0)