Skip to content

fix(lark): redact credentials from shared Lark sinks - #8181

Merged
huangruiteng merged 3 commits into
mainfrom
codex/lark-shared-sink-credential-redaction-20261106
Nov 7, 2026
Merged

huangruiteng merged 3 commits into
mainfrom
codex/lark-shared-sink-credential-redaction-20261106

Conversation

@JasonBuildAI

@JasonBuildAI JasonBuildAI commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Goal And Delivered Outcome

  • Outcome basis / optional anchor: Security hardening for the Lark presentation extension; no public issue was opened.
  • Goal/source and gap: Shared Kanban and Explore projection paths could serialize free-form Todo, worker-output, Evidence, Handoff, Explore and stage-document text without applying the canonical provider-credential shape owner. Shared visibility also stopped at top-level values, and the operator sync/seed/heartbeat commands did not consistently select the shared boundary.
  • Observable before -> after, with the validation row that proves it: Before, credential-shaped text could reach a shared Lark Base record or Explore surface and still be reported as public-safe. After, every affected record writer redacts canonical credential shapes before serialization; shared visibility recursively applies path/private-reference redaction to nested keys and values, and the operator commands propagate the selected visibility explicitly. tests/extensions/test_lark_shared_sink_redaction.py and tests/control_plane/test_public_safety_credential_shape_owner.py cover the before/after boundary.
  • Issue/task and intended base: No public issue; security hardening request. Intended base: upstream/main at ac6296225.

Author Declaration

  • Written by: model_agent (OpenAI Codex) at JasonBuildAI's direction.

Implemented against

  • Specification and revision: No public written specification; .github/SECURITY.md and the request in this PR are the basis.
  • Criteria:
Criterion (spec clause) Disposition Symbol / path Test or command
Shared Lark record writers remove canonical provider-credential shapes before serialization implemented loopx/extensions/lark/presentation/kanban.py tests/extensions/test_lark_shared_sink_redaction.py
Shared visibility redacts nested keys/values and preserves structurally valid record-link ids implemented _sink_safe_lark_values tests/extensions/test_lark_shared_sink_redaction.py
Operator sync, seed and heartbeat commands default to shared visibility and propagate it implemented loopx/cli_commands/lark_kanban.py tests/extensions/test_lark_shared_sink_redaction.py
Explore visual, stage-document and issue-fix paths use the same boundary implemented loopx/extensions/lark/presentation/explore_results.py, explore_stage_document.py, loopx/cli_commands/explore_feishu_commands.py tests/extensions/test_lark_shared_sink_redaction.py
Python and TypeScript credential-shape owners stay in sync implemented loopx/public_safe_text.py, loopx/control_plane/goals/vision_checkpoint.ts, packages/dsh-loopx-plugin/src/observer.ts tests/control_plane/test_public_safety_credential_shape_owner.py
Operator docs state the new default and residual limits implemented docs/integrations/lark-kanban-control-plane-adapter.md documentation review
  • Self-check before submission: Rebased onto ac6296225; ran the focused and adjacent Python suites, ruff, py_compile, root and plugin TypeScript typechecks, module ratchet, and public-boundary scan. Did not include live data, credentials, reproduction steps, or private paths. Historical rows already written to a shared Base are not automatically cleaned; exposed credentials still require revocation and rotation.

Scope And Continuation

  • Completed scope and remaining work: Complete for new writes in the affected Lark projection, Explore, operator sync and heartbeat paths. Historical shared records, exports, backups and already-exposed credentials require operational cleanup and rotation outside this code change.

  • Slice boundary / successor: N/A for code; advisory publication and release coordination remain with maintainers.

  • Default behavior change: sync-loopx-todos, seed-task, seed-cases and heartbeat now default to --sink-visibility shared. The explicit owner-only mode remains available when the target ACL is independently verified.

Validation

  • Tested revision: d2b6e838b607b633682536d9dcc08f79f12e358e
  • Run state: finished
  • Input classes: synthetic, public_fixture
Check kind Result Public-safe evidence / limitation
unit passed tests/extensions/test_lark_shared_sink_redaction.py and tests/control_plane/test_public_safety_credential_shape_owner.py: 175 passed.
unit passed Shared stage SVG regression: real presentation bundle -> shared stage write path -> independent XML parser: 1 passed.
unit passed Adjacent public-safety, Lark, Explore and presentation tests re-run after the review fix: 232 passed.
integration passed Explore source-runtime route tests: 6 passed.
static passed ruff, py_compile, git diff --check; root control-plane and plugin TypeScript typechecks.
regression_parity passed Module metric ratchet and public-boundary scan passed after the reviewed ceiling update.
manual blocked hot-path-interface-budget-smoke.py fails identically on pristine ac6296225 with entrypoint_missing; environment limitation, not this diff.
static blocked CI kernel-static-checks fails on F841 at tests/control_plane/test_goal_create_completion.py:184; that file is unchanged here (last touched by #8178) and the identical failure reproduces on base ac6296225 (run 42313186589, job 128219540019).
integration blocked dsh-loopx-plugin admission-closeout integration fails with invalid_schema; the same test fails identically on main at e7a6c8d5f (run 41961423900, job 127028426011). Linux CI passes observer.spec.ts 13/13.
static blocked checks, pytest, stage2c-correctness-e2e and merge-gate fail only as downstream gates: checks requires kernel-static-checks success, stage2c-correctness-e2e requires the skipped stage2c result to be success, and the Python shards were skipped the same way on base ac6296225.
unit blocked Local Windows dsh-loopx-plugin suite has pre-existing path-normalization failures; 200/208 plugin tests passed.
integration blocked cli-output-budget-regression-smoke.py fails on pristine main because the base fixture lacks read_cli_context_for_oracle; unrelated to this diff.
integration passed CI PostgreSQL authority real-server check passed.

UI Impact

  • UI impact: none
  • Before: N/A
  • After: N/A
  • First viewport and preview: N/A
  • States and viewports shown: N/A
  • Source data: none
  • Attention review: N/A
  • Craft review: N/A

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Refactoring (no functional changes)
  • Documentation update
  • Test update

LoopX Area

  • Control plane (goals, todos, quota, scheduler, registry, runtime)
  • Benchmark boundary (adapters, runners, verifiers, scoring, evidence)
  • Capability or extension (providers, adapters, skills)
  • Public docs or presentation surface (README, protocols, dashboard)
  • Build, packaging, installer, or CI
  • Host or runtime integration

Technical Direction

  • Direction / acceptance reference, when applicable: Core control-plane hardening and operator-surface/IM integration. No roadmap id is claimed by this change.

Shared-authority RFC fixture impact

  • Production-scale fixture schema: N/A
  • Semantic dimensions changed, or reviewed no-impact rationale: N/A
  • Provider conformance arms run: N/A
  • Read-only legacy/file/PostgreSQL three-arm rehearsal: N/A

Boundary Checklist

  • Neither the diff nor this PR body/comments/attachments disclose private state, credentials, raw traces or verifier output, internal links, or local machine paths (including .loopx/, .codex/goals/, and live ACTIVE_GOAL_STATE.md).
  • I did not duplicate maintainer-owned benchmark work unless a maintainer split out a public issue for it.
  • I kept the change scoped to the linked issue/task.
  • Existing English/Chinese RFC pairs (including ledger entries) both have a diff, and the local premerge check python3 scripts/check_rfc_bilingual.py --base origin/main --head HEAD passes, or no paired RFC changed.
  • I completed the visual evidence section for UI changes, or marked UI impact none.
  • Every commit includes a DCO Signed-off-by trailer (git commit -s).

Security Note

This PR intentionally limits vulnerability detail. The affected surface is the shared Lark projection boundary; the fix is shape-based redaction, not a complete DLP system. Historical data and any credential that may already have reached shared storage require revocation and rotation rather than relying on this code change.

@JasonBuildAI

Copy link
Copy Markdown
Contributor Author

CI note: kernel-static-checks fails in tests/test_chat_codex_history.py with three F811 redefinitions of steward/conversation. This PR does not touch that file; the same ruff check failure reproduces on pristine upstream/main at 62e234c. Leaving that unrelated repair out of scope.

@loopx-agent loopx-agent left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewer: model_agent | gpt-6.1-sol | OpenAI | runtime_reported | reasoning_effort=max

[P2] 先净化语义值,再渲染 SVG。 807e13bb6c94 的新增最终源码替换会在 shared 阶段图摘要链接位于文本末尾时吞掉 XML 闭合标签。独立格式解析器在 head 报 mismatched tag,隔离的子进程 provider 拒绝该文件,产品返回 publish_failed;同一基线输入、head 的 owner-only 和普通 shared 对照均有效。请在 SVG/Mermaid 编码前净化字段,补真实 builder→写入文件→独立格式解析的回归,保留 shared 边界。

动机 / Motivation

将 Todo、工作结果和 Explore 阶段图同步到共享飞书看板的操作者。

同一公开合成阶段摘要在基线生成有效 SVG;head shared 替换吞掉闭合标签,独立 XML parser 与隔离 provider 拒绝;owner-only 和健康对照有效。

真实 CLI seed 写入已消除合成凭据,关闭扩展时完整错误与退出码相同;共享可视化格式回归尚未修复。

不证明远端 ACL、实际 Lark 部署、历史记录清理、凭据轮换或完整 DLP;不改变执行/合并权限。

改动思路 / Approach

Detection, audience projection and provider IO have existing suitable owners; the required correction is filtering placement, without a new abstraction.

复用 public_safe_text 作为凭据形状 owner,现有 audience 值表达投影意图,cli_transport 和 marker readback 继续拥有外部写入与恢复。只增加顶层过滤不能覆盖嵌套字段;应在既有语义值接缝净化后编码 SVG/Mermaid,不增加状态或工作流。

共享输出净化及既有凭据镜像同步;必须修正可视化格式回归,历史清理/ACL/真实远端部署仍在范围外。

具体改动 / Changes

依据预变更规范 docs/integrations/lark-kanban-control-plane-adapter.md,固定 revision 62e234c939996ad42f2b1168451cc9a656dce11d,其 Review Boundary 对共享行的凭据、原始日志与本地路径边界在记录路径得到实现;不把该结果外推为可视化完整资格。全部差异为12文件、+1047/-71:包括递归净化、四个 CLI 参数传递、Explore 源码与阶段文档、Python/TS 形状同步、测试和指标基线。

关键代码讲解

  • _public_safe_value L507递归访问嵌套键、值、列表及 tuple,仅为结构合法的 record-link id 保留引用。
  • build_record_upsert_command L786在 JSON 序列化前再过滤凭据;owner-only 同样执行凭据边界。
  • sync_explore_visual_to_lark L832读取 renderer 源码后净化,再生成 delivery digest、写文件并核验 marker;本次 P2 就在新增的净化位置。
  • register_lark_kanban_commands L60为 seed/sync/heartbeat 复用 shared/owner-only,operator 默认改为 shared;显式 visual API 仍默认 owner-only。共享 Python 形状规则及 Vision/DSH 镜像也有意收紧凭据识别,并非仅在 Lark 开启时生效。

对主干的风险 / Risks

这是生产调用方可达的格式回归,不是测试 fixture 自身失败。已通过174项 focused、485项 adjacent、7项 TS corpus、13项 observer,root/plugin typecheck、mypy17项、改动 Python 的 Ruff 和 quick premerge 的6项直接检查;这些通过不能覆盖缺失的格式 oracle。18次真实源码 CLI 调用验证了 absent/enabled/disabled、preview/execute 和 provider refusal;关闭态完整错误与退出码相同,健康行字节一致,合成凭据在 head 写入中消失。格式反例使用真实 builder、源码文件、subprocess transport 和独立 XML parser,远端 provider 为隔离合成进程,未连接真实 Lark。公开边界扫描无错误;6条非字面 regex/合成引用提示已逐条核对。按当前策略未查询或等待 CI,作者附带的红灯只作未归因诊断。

语义与 CI 对齐

复用既有 visibility 词汇,没有新增状态协议。发现的是当前有效 SVG 契约被新文本替换破坏;不应靠放宽 parser、隐私规则或改用 owner-only 为共享看板绕过。修复后需重跑实际两种 renderer 的语义值与格式负例,并检查完整新 head。

我的整体评价 / Verdict

改动规模与共享输出缺口基本相称;无需额外框架,后续可在修复接缝时合并重复遍历。长期控制语义在已测路径保持,尚无长期收益结论;用户体验存在确定回归,整体交付 not_yet_proven。检查了真实 builder 生成并交给 subprocess transport 的 SVG;独立 XML 解析已发现回归,不能据此宣称远端视图可用。真实 Lark 全页面、窄屏、展开交互及 ACL 未测试。记录净化的成功不足以批准这个完整 head。

English verdict: REQUEST_CHANGES — HEAD 807e13b; shared SVG sanitization corrupts markup; repair before approval.

Remove canonical provider credential shapes before record serialization, including nested values and worker output, while retaining existing redaction for shared board paths and private references.

Default operator todo sync, seed, and heartbeat paths to shared visibility so documented shared boards do not require an opt-in. Route automatic issue-fix Explore sync and CLI-linked Explore refresh through the same visibility.

Mirror the expanded credential shapes in both TypeScript owners and apply the visibility-aware boundary to seed-task and seed-cases.

Signed-off-by: JasonBuildAI <jasonbuildai@gmail.com>
Record the accepted shared-sink redaction growth: explore_results.py adds 34 lines, while kanban.py adds five Any annotations and its line ceiling is tightened from 2791 to its current 2760. No additional runtime behavior is introduced by this baseline update.

Signed-off-by: JasonBuildAI <jasonbuildai@gmail.com>
Redact node titles, summaries and blocked reasons plus edge types and
summaries before SVG or Mermaid is encoded. Re-render a role view from the
sanitized values when redaction changes display text, so stage titles, stage
SVG and overview diagrams stay consistent while the source digest and
freshness contract keep their original semantics.

Keep the shared visibility boundary for caller-supplied pre-rendered views by
rewriting decoded SVG text spans and Mermaid labels only; the previous
whole-source replacement could consume a closing </text> after a private link.

Add a regression that builds the real presentation bundle, publishes through
the shared stage write path and parses the written SVG with an independent XML
parser. Record the reviewed module metric growth.

Signed-off-by: JasonBuildAI <jasonbuildai@gmail.com>
@JasonBuildAI
JasonBuildAI force-pushed the codex/lark-shared-sink-credential-redaction-20261106 branch from 807e13b to d2b6e83 Compare November 7, 2026 01:07
@JasonBuildAI

Copy link
Copy Markdown
Contributor Author

已按当前 head 复核并更新 PR 描述里的验证证据;head 未变:d2b6e838b607b633682536d9dcc08f79f12e358e,base ac6296225。

当前 head 的 CI 失败已与基线逐一对照,均不由本 diff 引入:

  • kernel-static-checks:F841 at tests/control_plane/test_goal_create_completion.py:184。该文件不在本 PR diff 内(最近由 Retain approved Goal completion criteria before first dispatch #8178 修改),基线 ac6296225 的同一 job 复现同样错误(run 42313186589 / job 128219540019)。
  • checks、pytest、stage2c-correctness-e2e、merge-gate:都是上述门禁的下游结果(checks 要求 kernel-static-checks success,stage2c-correctness-e2e 要求 stage2c 结果为 success 但实际 skipped),基线同样为红。
  • dsh-plugin (ubuntu-latest):tests/admission-closeout.integration.spec.ts 报 invalid_schema;main 在 e7a6c8d5f 上同一测试、同一行同样失败(run 41961423900 / job 127028426011)。

本 diff 范围内的结果:

  • pytest tests/extensions/test_lark_shared_sink_redaction.py tests/extensions/test_lark_kanban_schema_preflight.py tests/test_explore_presentation_views.py tests/test_explore_owner_board_views.py tests/control_plane/test_public_safety_credential_shape_owner.py -q:232 passed。
  • dsh-plugin (windows-latest)、postgresql-authority (real server)、dependency-review、Sign-off 通过。
  • [P2] 修复保持在 d2b6e838b:SVG/Mermaid 编码前净化语义值;真实 builder -> 共享写入路径 -> 独立 XML parser 回归 1 passed。

checks 失败会让 Python 分片被跳过,待 main 的 lint 项修复后可在本 head 重跑。若希望在本 PR 内附带那行测试 F841 修复以解除门禁,请告知;默认不扩大本 diff 范围。请复审。

@loopx-agent loopx-agent left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewer: model_agent; gpt-6.1-sol; OpenAI; runtime_reported; reasoning_effort=max.

动机 / Motivation

将 Todo、工作结果和阶段图同步到共享飞书看板的操作者。

此前共享记录可能带出凭据形状;上一版修复又会破坏阶段 SVG。当前实际 CLI 写入已净化合成凭据,阶段图保留有效 XML 并完成隔离写入和回读。

独立232项 Python、33项 TypeScript 和13项 observer 检查通过;真实 CLI 的 absent/enabled/disabled/refusal 与 shared/owner-only 写入经验证,旧 SVG 反例被独立 parser 拒绝,当前路径通过。

不证明远端 ACL、实际 Lark 部署、历史共享记录清理、凭据轮换或完整 DLP;不改变执行和合并权限。

改动思路 / Approach

规范识别 owner、既有 visibility 投影和 provider IO 的责任划分适合此修复;先净化语义显示值再编码,保留预渲染兼容路径的格式边界,无须另建状态或工作流。 当前 PR 交付受影响新写入的安全投影及格式修复;实际远端 ACL、存量清理和部署验收在此范围外。

原数据 → 净化语义值 → 编码或记录序列化 → 既有 provider 写入 → 独立结果回读。顺序来自源码检查,格式/行为证据来自后述真实执行,不将图示或摘要当作测试。

具体改动 / Changes

规格取预变更 docs/integrations/lark-kanban-control-plane-adapter.md,spec_revision ac62962。逐项映射:Review Boundary=implemented;Authentication Boundary=implemented;CLI Surface=implemented。并对照 docs/public-private-boundary.md 同版本的 Credentials 契约。

全差异12文件、+1294/-80;递归记录净化、操作入口、Explore 显示值和 Python/TS/DSH 形状同步都已检查。没有只复跑最后一个用例。共享与 owner-only 使用相同凭据边界,后者保留其既有路径可见性。复用既有 visibility 词汇,regex 识别文本形状,不用于分类工作状态。

关键代码讲解

  • _public_safe_value:Top-level text filtering -> recursive nested key/value filtering with valid record-id preservation;Destination-specific redaction, no authority inference。
  • _redact_explore_display_values:Display values sanitized before rendering; topology fields retained;Never apply whole-text regex to raw markup。
  • sync_explore_visual_to_lark:Format-aware rendered-label fallback before digest and publication;Parseable markup, unchanged source freshness, truthful marker readback。
  • register_lark_kanban_commands:Operator defaults to shared, explicit owner-only retained;Activation and external execute remain separate。

对主干的风险 / Risks

原公开 P2 的完整 review 和 inline 已逐条映射:旧整段替换会吞闭合标签;当前语义值层过滤后编码,并为预渲染调用方只重写文本/标签。八节点长重复内容、四种状态的独立 XML parser 在历史管线反事实报 mismatched tag,在当前管线通过。实际源 CLI 经隔离 subprocess 验证记录写入、扩展拒绝、provider 拒绝及恢复;没有接触真实 Lark。最初探针把临时源文件清理和幂等不重写误作失败,修正证据捕获/幂等 oracle 后按同输入完整重跑,保留其原始结果,不归因产品。

232项 focused/adjacent Python、33项 corpus/Vision TypeScript、13项 observer、root/plugin TypeScript 和配置17入口 Mypy 全过。 quick premerge 的6个直接、4个选择检查机械通过;整体仍因严格质量门 HOLD。必检 Ruff 的 test_goal_create_completion.py:184 F841 在不可变 base/head 完整归一化诊断相同,因果文件和配置未改;不要求本 PR 顺手修改无关代码,严格 CQR 仍为 FAIL,不能据独立 APPROVE 宣称可合并。

语义与 CI 对齐

默认 shared 的行为改变已在操作文档和 PR 明示;显式 visual API 仍默认 owner-only。canonical shape 的安全收紧不限于 Lark 开启态,benign prose 与镜像测试通过;不把这部分说成 feature-off 完全不变。已有扩展 gate 的完整拒绝诊断和无 IO 经 base/head 配对验证。 本轮未查询、轮询、等待或触发 CI;作者附带的远端红灯保留为未独立归因诊断。未把文本 redaction 声称为完整 DLP;历史存量和远端权限没有因此自动解决。

我的整体评价 / Verdict

当前 exact head d2b6e83 的已验证源码切片支持 APPROVE;long_horizon=preserved,user_experience=improved,仅限上述来源/恢复或共享输出路径,不外推为长期净收益。规范识别 owner、既有 visibility 投影和 provider IO 的责任划分适合此修复;先净化语义显示值再编码,保留预渲染兼容路径的格式边界,无须另建状态或工作流。 当前 PR 交付受影响新写入的安全投影及格式修复;实际远端 ACL、存量清理和部署验收在此范围外。

已检查实际 builder 生成并交给写入路径的完整阶段 SVG:八个长标题、重复摘要及 ACTIVE/DONE/BLOCKED/FAILED 混合状态,净化标记可读,卡片与状态保持。顶部长总标题沿既有画布裁切,格式修复没有改变其几何属性。 真实 Lark 全页面、远端 ACL、窄屏缩放与交互未验证;本 PR 未改变响应式布局。 原有长总标题的裁切未计为本 PR 新回归或已修复项。 保留原讨论、历史失败、严格 CQR 和 readiness 的独立门;本轮没有合并、dismissal、共享安装、Host 切换或付费执行。

English verdict: APPROVE

@huangruiteng
huangruiteng merged commit 65b0295 into main Nov 7, 2026
28 of 35 checks passed
@huangruiteng
huangruiteng deleted the codex/lark-shared-sink-credential-redaction-20261106 branch November 7, 2026 07:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants