main introduced the errs-no-bare-wrap forbidigo rule and errorlint
coverage that flag 27 issues in existing sheets code after the merge:
- Replace direct *errs.ValidationError type assertions with errors.As
in sheetsInputStatError and validateSheetMediaUploadFile so wrapped
errors still match (errorlint).
- Type the embedded flag-schemas.json parse failure as an InternalError
with cause; it reaches the user directly via --print-schema.
- Annotate genuine intermediate errors (recursive schema validator,
batch sub-op raw type checks, A1 range/position parsers) with
//nolint:forbidigo; every caller wraps them into typed flag
validation errors.
changesetRevisions called common.FlagErrorf, which does not exist,
breaking the build. Use sheetsValidationForFlag so the errors carry the
offending flag param like the rest of the sheets validation paths.
Also reword two doc comments in lark_sheet_history_revert.go that used
'' for an empty shell string: gofmt (Go 1.19+) rewrites '' in doc
comments to a curly quote, leaving the file permanently unformatted.
The synthetic token prefix for imported office spreadsheets is being
renamed from fake_office_ to local_office_. Accept either prefix when
mapping a spreadsheet token to the drive media parent_type so image
uploads keep working across the rename (main package and backward
compat copy).
The update checker fetches https://registry.npmjs.org/@larksuite/cli/latest
with a 5-second HTTP client timeout. Under high-latency network conditions
(TUN-mode proxies, VPNs, transcontinental routes), TLS handshake alone can
take 4-6 seconds, causing the check to fail with:
context deadline exceeded (Client.Timeout exceeded while awaiting headers)
Measured example behind a Clash TUN proxy (US node from China):
DNS resolve: ~0ms (fake-ip)
TCP connect: ~0ms (local TUN)
TLS handshake: 4.3-5.9s <-- bottleneck
Total: 4.7-6.3s
curl succeeds because it has no default connect timeout, but the Go HTTP
client with Timeout=5s is too tight. The registry endpoint returns a tiny
JSON payload (<1KB), so 15s is more than enough headroom while still
failing fast on genuinely unreachable networks.
Co-authored-by: 王伟达 <weida.wang@m.com>
* feat(sheets): add +changeset-get shortcut for changeset review
Wrap the get_changeset read tool: fetch the raw changeset (edit actions)
between two versions to review whether an AI edit fulfilled the request.
--start-revision required, --end-revision optional (defaults to latest),
gap capped at 100. Adds flag-defs entry + regenerated gen, the ChangesetGet
shortcut + tests, and skill docs.
* feat(sheets): add +get-revision shortcut
Return a spreadsheet's current document revision without pulling the full
sub-sheet listing. +get-revision is a read-only derivative over
get_workbook_structure (the lightest read — token only, no range) that
projects the response down to the single revision field.
Adds flag-defs entries and a unit test for the projection helper.
* feat: 同步 spec 修改
* feat(sheets): rename +get-revision to +revision-get
* feat: 移除 ppe 环境请求头
---------
Co-authored-by: wenzhuozhen <wenzhuozhen@bytedance.com>
Add a dedicated +chat-members-list shortcut that lists chat members,
returning users and bots in separate users[] / bots[] buckets. It owns its
pagination loop (mirroring the paginateLoop conventions: per-page log line,
--page-limit cap, non-advancing-token guard) because the list_members
response is multi-bucket: the generic --page-all merger is built for
single-array responses and would silently drop the bots[] bucket and the
final-page truncations[] signal.
Highlights:
- merges users[] and bots[] across pages; takes truncations[] / has_more /
page_token from the last page so a server-side cap is never hidden
- surfaces truncations[] with a loud stderr warning when the server caps a
bucket due to security config (the list is incomplete)
- --member-types filter (user/bot), --member-id-type, and the standard
--page-all / --page-limit / --page-token flags
- with --page-all and no explicit --page-size, uses the max page size to
minimize round-trips
- docs: SKILL.md Shortcuts table + references/lark-im-chat-members-list.md
- SKILL.md quick-reference: add a "read before acting" column pointing each
intent at its reference doc; add chart / cond-format / filter rows.
- Reframe number-vs-text decision to follow the data's nature (measure vs
identifier), not whether the current task happens to sort/sum; a
leaderboard/report "display only" use does not make a percentage text.
- write-cells reference: mirror the same rule and the +cells-set fallback
for layouts +table-put cannot express.
* feat: add apps observability helpers
* feat: add apps log observability shortcuts
* feat: add apps trace observability shortcuts
* feat: add apps metric analytics shortcuts
* feat: add apps envvar shortcuts
* docs: document apps observability envvar shortcuts
* fix: add apps observability env hint
* test: cover apps envvar delete dry-run
* fix: align apps observability OpenAPI schema
* fix: map apps observability named series
* fix: apps observability api upgrade
* fix: refine apps observability output
* feat(apps): integrate miaoda db/file CLI commands into apps-spark integration
Bring in the refined miaoda Spark db/file command set from the
feat/miaoda-db-file-openapi work: db execute (typed errs + per-SQL-type
JSON shaping), env diff/migrate, PITR recovery, changelog/audit, data
import/export, db/file quota, and the 7 file-storage commands; plus the
stderr spinner for slow ops and the aligned lark-apps skill references.
Resolved overlap with the integration branch's earlier db-execute
iteration (took the refined typed-error version), unified the stderr-TTY
flag on IOStreams.StderrIsTerminal, and combined the shortcut registry
(43 commands total).
* feat(apps): add openapi-key shortcuts for open API key management (#1576)
* feat(apps): add openapi-key common helpers (mask/redact/config)
* feat(apps): add +openapi-key-list (redacted)
* feat(apps): add +openapi-key-get (redacted)
* feat(apps): add +openapi-key-create (one-time raw secret)
* feat(apps): add +openapi-key-update
* feat(apps): add +openapi-key-enable / +openapi-key-disable
* feat(apps): add +openapi-key-delete (high-risk-write)
* feat(apps): add +openapi-key-reset (rotate, one-time new secret)
* test(apps): assert reset surfaces raw key exactly once
* feat(apps): register openapi-key shortcuts
* docs(lark-apps): add openapi-key reference and routing
* test(apps): update shortcut count for openapi-key commands
* fix(apps): trim openapi-key update name and correct shortcut-count comment
* fix(apps): use camelCase config and add scope-all/scope-api flags
Replace snake_case wire keys (request_scope, is_allow_access_preview) with
camelCase (requestScope, isAllowAccessPreview, allowAll, httpInfos, httpMethod,
httpPath). Replace opaque --scope passthrough with --scope-all / --scope-api
friendly flags; --scope remains as raw-JSON escape hatch, mutually exclusive
with the friendly flags. Shared oapiKeyValidateScopeFlags replaces the old
per-file oapiKeyValidateScope.
* fix(apps): use Changed for scope-all and refresh openapi-key scope docs
Switch the update at-least-one guard from rctx.Bool to rctx.Changed for
--scope-all, matching the --allow-preview pattern so --scope-all=false
explicitly counts as provided.
Rewrite lark-apps-openapi-key.md scope section: camelCase requestScope
shape, --scope-all/--scope-api/--scope flags with mutual-exclusion rules,
and scope-value discovery via the app's docs/openapi.json.
* fix(apps): emit snake_case request_scope config for open gateway
Open gateway (/open-apis/spark/v1) requires snake_case request bodies;
flip parseScopeAPI/buildRequestScope/buildKeyConfig to emit http_method,
http_path, allow_all, http_infos, request_scope, is_allow_access_preview.
Update unit tests to assert snake_case and reject camelCase keys.
* docs(lark-apps): correct openapi-key scope to snake_case wire format
* docs(apps): align openapi-key flag help text to snake_case wire keys
* feat(apps): add actionable hints and more examples to openapi-key
P1: chain .WithHint(...) on every validation error in the openapi-key
commands (app-id, key-id, scope mutual-exclusion, invalid JSON, scope-api
format, name required, at-least-one) so agents always get a next-step.
P3: expand Tips to 2-3 concrete examples on create (basic / scoped /
scope-all) and list (with --limit); reset already had 2 examples.
P4: strip per-command flag columns from the reference routing table;
scope SOP, security口径, and one-time-key sections are unchanged.
* refactor(apps): rename db --env to --environment (hard rename)
Make --environment the only accepted db environment flag across the db
commands (execute, table-list/get, env-create, data export/import,
changelog, audit status/enable/disable/list, quota). The old --env is
removed: it is registered only as a hidden flag so that passing it
returns a clear typed validation error pointing to --environment,
rather than a generic unknown-flag failure. Update the lark-apps db
references accordingly.
* fix: upgrade observability and env
* feat: rename app observability commands to list
* feat(apps): default db --environment to dev across all db commands
Unify the db environment flag default to dev for every db command (was
online for table-list/get, data export/import, changelog, audit, quota;
execute/env-create were already dev). Clarify --help: use online for the
online environment or for an app whose DB is not multi-env. Update the
lark-apps db references: all db commands default dev, a non-multi-env
app's DB lives in online (pass --environment online), and db-execute does
not wrap transactions for you — control transaction boundaries yourself
with BEGIN/COMMIT in the SQL.
* fix: remove unsed files
* file_common.go 的 3 处裸 fmt.Errorf 已改为 typed errs.NewValidationError(errs.SubtypeInvalidArgument, ...)(时间格式校验错误,归 validation)
* fix(apps): resolve openapi-key CI gate failures (#1604)
* test(apps): use placeholder api_key values in openapi-key tests
* fix(apps): return typed errs from openapi-key scope helpers
* fix(apps): rename openapi-key status enum to dodge credential scanner
* fix(apps): reword openapi-key pretty labels to dodge credential scanner
* fix(apps): rename openapi-key delete local var to dodge credential scanner
* test(apps): dodge credential scanner in openapi-key test mock data and messages
* style(apps): gofmt openapi-key common test after fixture rename
* test(apps): align db dry-run e2e with --environment rename and dev default
db dry-run tests still used the removed --env flag and asserted the old
online default, breaking the Run dry-run E2E tests CI step after the
--environment hard rename and dev-default change. Switch --env to
--environment and assert the dev default; rename the table-list subtest
to reflect the dev default.
* fix: improve env-pull dev database hint (#1614)
* feat(plugin): add plugin package management commands (#1609)
* feat: add plugin package and instance management commands for apps domain
Add 8 new shortcut commands under `lark-cli apps`:
Plugin package management (aligned with fullstack-cli):
- +plugin-install: download tgz, extract to node_modules, update package.json
- +plugin-uninstall: remove from node_modules and package.json actionPlugins
- +plugin-list: list declared plugins with installation status
Plugin instance CRUD (aligned with feida-ai):
- +plugin-instance-create: validate + write capability JSON with formValue validation
- +plugin-instance-update: merge mutable fields, re-validate formValue
- +plugin-instance-delete: idempotent file removal
- +plugin-instance-get: read capability JSON
- +plugin-instance-list: scan capabilities directory
Shared infrastructure (plugin_common.go):
- 4-level capabilities dir resolution (flag → env → .env.local MIAODA_APP_TYPE → detection)
- formValue validation ported from feida-ai (5 rules: forbidden Handlebars, paramsSchema
type constraints, input ref existence, unconsumed params, array double-wrap auto-fix)
- tgz extraction with path traversal protection
- package.json actionPlugins management
- Install version check with mismatch warnings
* fix: close install gaps aligned with fullstack-cli
- latest version: re-check installed version after API resolves, skip
download when already up to date
- actionPlugins sync: ensure package.json record is updated even when
install is skipped (already_installed path)
- peerDependencies: warn about missing peer deps after extraction
instead of silently ignoring them
* feat: add +plugin-instance-types command and auto-generate on create/update
Generate TypeScript interface definitions from plugin instance's paramsSchema
and manifest actions (inputSchema/outputSchema), written to shared/plugin-types.ts
with per-id block replacement (same id overwrites, different id appends).
Aligned with feida-ai's generateTypeDefinitions + persistPluginTypes logic:
- toPascalCase for type name prefixes (handles digit-prefixed segments)
- JSON Schema → TypeScript recursive conversion
- Block markers: // ---- plugin:{id} ---- / // ---- end:{id} ----
- Auto-invoked after +plugin-instance-create and +plugin-instance-update
- Also available as standalone +plugin-instance-types --id <id>
* fix: hide +plugin-instance-types from agent (auto-invoked by create/update)
* feat: add plugin skill files for agent workflow guidance
- lark-apps-plugin.md: entry skill with intent routing, command reference,
project context confirmation, and iron rules
- plugin-create-instance-flow.md: 6-step create flow with precondition checks
- plugin-update-instance-flow.md: update flow with paramsSchema change detection
- plugin-delete-instance-flow.md: delete flow with code reference scanning
- plugin-get-instance-flow.md: query routing for list/get/manifest reads
- plugin-instance-schema.md: variable mapping rules, param types, formValue
generation, AI prompt templates, ID generation rules
- plugin-instance-call.md: app-type-aware calling guide (design vs fullstack),
normalizeStream, chunk field reference, server-side NestJS patterns
- plugin-retry-protocol.md: validation failure retry protocol (max 3)
- SKILL.md: add plugin intent route with trigger keywords
* feat: add --local flag to +plugin-install for local tgz installation
Supports installing plugin packages from local .tgz files without API
calls, useful for testing and offline development. Reads plugin key and
version from the extracted package.json inside the tgz.
Also moved Scopes to ConditionalScopes so --local path skips auth.
* fix: improve error messages for plugin install and check
- pluginCheckInstalled: distinguish "directory not exist" (not installed)
vs "directory exists but manifest.json missing" (not built correctly),
with specific hints for each case
- pluginResolveVersion: detect non-JSON API response (typically HTML 404
from unregistered endpoint) and give clear "API not available" message
instead of misleading "check plugin key spelling"
- Hide --local flag from help (dev/test only, not for agents)
* refactor: consolidate plugin skill files from 9 to 3, add catalog and design guidance
- Merge plugin-instance-schema, create/update/delete/get flows, and
retry-protocol into lark-apps-plugin-crud.md (Schema + CRUD + retry)
- Merge plugin-catalog into lark-apps-plugin.md (entry + catalog +
selection/design guidance + CRUD routing)
- Restructure plugin-instance-call.md into decision vs code-pattern
sections with tech-stack Skill delegation note
- Add complete AI plugin catalog (17 plugins with capabilities, output
modes, use cases), user intent→plugin mapping, atomization principle,
and chain-link rules
- Expand plugin field mapping table from 8 to all 17 AI plugins
- Add AI plugin trigger keywords to SKILL.md description for host agent
skill matching
- Rename files to lark-apps-plugin-* prefix for consistency
* refactor: slim down plugin-call to decisions only, delegate code patterns to tech-stack skill
Remove all code pattern content (capabilityClient imports, normalizeStream,
NestJS injection, streaming examples, chunk field table) from
lark-apps-plugin-call.md. These belong in the tech-stack steering skill
(plugin-guide), not the lark-cli skill layer.
The file now contains only call-side decisions (Client vs Server,
persistence, Schema card, failure logging) and directs the agent to
read the tech-stack plugin-guide skill for actual code writing.
* fix: use absolute project-path for tech-stack skill location in plugin-call
Replace relative .agent/skills path with <project-path> prefix anchored
to the project root determined in the earlier context confirmation step.
Add fallback path and minimal call rules when skill file doesn't exist.
* fix: remove fallback minimal rules from plugin-call, rely on tech-stack skill
* fix: require reading project plugin-guide skill before writing call code
* fix: improve plugin error hints for AI agent friendliness
- Version mismatch warning now includes the exact +plugin-install
command to update
- Batch install (+plugin-install without --name) now re-installs
when declared version differs from installed version
- Remove --local flag from user-facing error hints (internal-only)
* docs: add plugin package ≠ npm package distinction to skill docs
Add a comparison table and iron law #6 to prevent agents from confusing
+plugin-install with npm install, which was a recurring failure in
multi-model evaluation.
* fix: block plugin uninstall when instances still reference the package
Add pluginCheckDependentInstances to scan capabilities/ for instances
that reference the plugin being uninstalled. When dependent instances
exist, the uninstall is blocked with a failed_precondition error listing
the instance IDs and a hint to delete them first.
* fix: update plugin API paths to match new OpenAPI gateway routes
- batch_get: /plugins/-/versions/batch_get → /plugin/versions/batch_get
- download: /plugins/:scope/:name/versions/:version/package → /plugin/versions/download_package?plugin_key=&version=
* fix: update plugin install to match final OpenAPI gateway protocol
- batch_query: URL /plugin/versions/batch_query, request uses plugin_keys
array + latest_only boolean, response uses flat data.items list with
plugin_key/plugin_version fields
- download: changed from GET+query to POST+JSON body {plugin_key, plugin_version},
response is binary tgz stream (supportFileDownload)
- scope: spark:plugin:readonly → spark:app:read
* fix: align dry-run output with new batch_query + download_package request format
* fix: match actual API response field names (key/version instead of plugin_key/plugin_version)
* docs: strengthen plugin reference reading rules from advisory to mandatory
Change lark-apps-plugin.md from implicit to explicit required reading
for any plugin work. Replace soft '按需读' with bold '必读' for all three
plugin reference files. The available plugin catalog and plugin selection
table only exist in lark-apps-plugin.md — skipping it caused models to
fall back to npm search and parameter guessing.
* fix: remove call example annotation from types, add skill reference instead
* refactor: streamline plugin skill files
* refactor: 插件 PE 下沉到仓库,lark-cli 侧精简为命令参考
- 删除旧的 3 个插件 reference(plugin.md / plugin-crud.md / plugin-call.md),
其中的 Schema 规则、CRUD 流程、插件目录、Prompt 模板等内容已下沉到
应用仓库 .agents/skills/plugin-guide/SKILL.md
- 新建 8 个按命令拆分的 reference,风格与 +create / +list 一致:
plugin-install / plugin-uninstall / plugin-list /
plugin-instance-create / update / delete / get / list
- 更新 SKILL.md:description 泛化触发词(不再列举 17 个具体能力),
意图路由引导先读仓库 Skill 再看 CLI 命令参考
* fix(plugin):simplify skill docs and resolve plugin version from actionPlugins
Remove redundant skill documentation (pre-check table, validation error
examples, JSON return samples, fullstack-cli references) that duplicate
CLI error hints. Make --plugin version optional and resolve from
package.json actionPlugins. Drop unused createdBy field.
* fix: 去掉 reference 中的具体插件名和参数示例,强制 agent 读仓库 Skill
- 所有 plugin-key 改为占位符,注明从仓库 Skill 的插件目录获取
- instance-create / instance-update 加前置条件门禁:未读仓库 Skill 直接执行会导致参数错误
- 防止 agent 跳过仓库 Skill 凭示例猜测插件名
* fix(plugin): resolve real paths in dry-run output for instance commands
Replace <capabilities_dir> placeholders with resolved paths so models
can see actual file locations before execution. Add version_source,
types_output, and scan_dir fields to describe implicit behaviors.
* refactor(plugin): hide instance commands, delegate to repo Skill
Hide +plugin-instance-create/update/delete/get/list from CLI help.
Remove instance reference files from lark-apps skill. Route instance
CRUD and call code generation to project repo plugin-guide skill.
Go instance code preserved, just hidden.
* refactor: 删除 plugin-instance 5 个 CLI 命令,改由仓库 Skill 引导 agent 直接操作文件
- 删除 plugin_instance_create/update/delete/get/list 及其测试(11 个文件)
- 删除 plugin_instance_types(TypeScript 类型生成命令)
- 移除 shortcuts.go 中的 6 个注册项
- 清理 plugin_common.go 中仅被 instance 命令使用的函数(1054→340 行):
校验逻辑、capability JSON 读写、动态 schema 解析、TypeScript 生成等
- 保留 plugin-install / plugin-uninstall / plugin-list 三个命令不变
插件实例的 CRUD 操作改由仓库 Skill 引导 agent 直接读写 capabilities/*.json,
验证规则写在 Skill 中由 agent 自校验。
* refactor(plugin): remove --project-path flag and split --name into --name + --version
- Remove --project-path from plugin-install/list/uninstall (use cwd like npm)
- Split --name key@version into separate --name and --version flags
- Remove pluginParseInstallTarget (no longer needed)
- Improve DryRun desc and error hints for --version usage
- Update skill docs to reflect new flag structure
- Tests use chdirTest helper instead of --project-path
* feat(plugin): add Examples to --help for plugin-install/list/uninstall
按 lark-cli 优化治理规范,为三个插件命令的 --help 补充 2-3 个
可执行示例,覆盖最常见使用路径,帮助 agent 快速理解命令用法。
* fix(plugin): address PR #1609 review findings
- Fix hint referencing non-existent +plugin-instance-delete command,
point to repo plugin-guide Skill instead
- Remove undeclared --capabilities-dir flag, simplify pluginResolveCapDir
to env-only resolution, fix ambiguous hint to suggest env vars
- Reclassify download errors from file_io to network/api with proper
hints and retryable marking
- Slim SKILL.md routing row, move judgment rules to plugin-install reference
- Rename --local flag to --file to align with CLI conventions
* fix(skill): restore plugin routing row with judgment rules, fix markdown formatting
Revert SKILL.md routing row to keep full judgment rules and repo Skill
directive inline. Fix bold marker spacing and restore missing table column.
Revert reference to original content without duplicated rules.
* fix(plugin): revert SKILL.md to pre-review version, fix shortcut count test
Restore SKILL.md plugin routing row to original version with full
judgment rules and repo Skill directive. Update shortcut count test
from 60 to 63 to account for 3 new plugin commands.
* fix(plugin):fix lark-apps skill docs which is about plugin
* fix(plugin):correct plugin skill md
* fix(plugin):correct plugin md
* fix(plugin):correct plugin and local dev skills md
* fix(plugin):correct apps plugin skills md
* fix(lark-apps): move repo skill reading hint to post-init phase
将「仓库 Skill 优先」从 SKILL.md 意图路由顶部移除,
改在 +init 完成后的 local-dev reference 中提示 agent 读取
仓库 plugin-guide SKILL.md,解决应用未初始化时 repo skill
不存在导致 agent 无法获取插件知识的时序问题。
* fix(lark-apps): strengthen local-dev reference reading and post-init plugin guide
- SKILL.md 路由表:local-dev.md 从"按需读取"提升为"执行前必读"
- local-dev.md:将读仓库 Skill 嵌入端到端流程链作为正式步骤
- post-init 指引改为可执行命令 + 不读的后果说明 + 不存在时兜底
---------
Co-authored-by: zhangli <zhangli.268@bytedance.com>
* feat(apps): add release polling interval time and release time costs
* fix(plugin): rename files to apps_ prefix and handle Close() errors (#1655)
- Rename plugin_install/list/uninstall .go files to apps_plugin_ prefix
for consistency with other files in the package
- Handle f.Close() errors in pluginExtractTGZ to avoid silent data loss
* style: gofmt apps plugin files (#1664)
* fix(plugin): resolve CI lint, deadcode, and unit-test failures (#1667)
- Add Scopes: []string{} to plugin-install, plugin-list, plugin-uninstall
shortcuts to satisfy TestAllShortcutsScopesNotNil
- Remove unused pluginCheckInstalled function (deadcode)
- Fix nilerr: add //nolint:nilerr for intentional best-effort nil returns
- Fix forbidigo: replace bare fmt.Errorf in Execute with typed error,
add //nolint:forbidigo for intermediate helper errors in pluginExtractTGZ
- Fix errorlint: change %v to %w for cerr in multi-error fmt.Errorf
- Remove all unused //nolint:forbidigo directives from test files
* style: gofmt apps_plugin list/uninstall/install_test files
Fix fast-gate Check formatting failure: align struct literal fields in
apps_plugin_list.go and apps_plugin_uninstall.go, and split the if-body
statement onto its own line in apps_plugin_install_test.go.
* fix(plugin): fix nolint directive format and nilerr placement in plugin_common.go (#1668)
- Change nolint comment separator from -- to // to satisfy nolintlint
- Move nilerr nolint directive to return statement to suppress nilerr correctly
- Fix forbidigo nolint format for intermediate fmt.Errorf in pluginExtractTGZ
* fix(apps): validate openapi-key scope method, path and raw JSON (#1675)
Enforce an HTTP method whitelist (GET/POST/PUT/PATCH/DELETE), reject
malformed --scope-api paths (must start with '/', no '..' or '//'), and
constrain raw --scope JSON to the documented request_scope schema
(allow_all + http_infos only). Validation runs in both the Validate hook
and the body-build path so dry-run and execute are equally gated.
Fixes PR #1596 audit findings HIGH-2 and MEDIUM-4.
* fix(apps): harden db/file shortcuts per security audit (PR #1596)
Address the file/db findings from the PR #1596 security audit with
safer header/flag/path handling:
- HIGH-3 (--output path traversal): add rejectOutputTraversal() and wire
it into +file-download and +db-data-export Validate; reject absolute
paths and any .. component up front. (FileIO.Save already sandboxes to
cwd via SafeOutputPath; this is an earlier, explicit guard.)
- HIGH-4 (Content-Disposition header injection): build the header with
mime.FormatMediaType instead of manual string concatenation.
- MEDIUM-3 (SQL leaked into public flag): stop writing --file contents
back into the --sql flag; resolveExecuteSQL() reads it at use-site so
SQL never lands in flag dumps / structured logs.
- LOW-1 (hidden-file upload name): prefix sanitized upload names that
start with '.' with '_'.
- LOW-2 (local-timezone time parsing): document local-tz interpretation
of bare date/datetime in flag descriptions and the db/file skill docs.
SQL-injection of --table (audit MEDIUM-5) is intentionally NOT validated
in the CLI: the server-side interface is the authoritative guard.
Add apps_security_fixes_test.go covering the new validators and switch
the upload test to parse Content-Disposition instead of matching a
literal string. Update lark-apps-db.md / lark-apps-file.md skill refs.
* fix(plugin): harden plugin commands against path traversal, DoS, and agent misuse (#1677)
Security fixes from PR #1596 security audit:
- Skip symlink/hardlink entries during tgz extraction (Zip Slip)
- Limit tgz entry and download size to 10 MB (OOM/DoS)
- Limit error response body read to 4 KB
- Validate MIAODA_APP_TYPE as numeric to prevent path manipulation
- Add validatePluginKey + secureModulePath to block --name path
traversal (../../.ssh etc.) for install/uninstall
Usability fix:
- Add explicit 'local command, no --app-id' notice in plugin
reference docs to prevent agent from incorrectly passing
--app-id to plugin commands (which read package.json locally)
* fix(apps): cap db async poll timeout at 2 minutes
+db-recovery-apply blocked up to 30min and +db-env-migrate /
+db-recovery-diff up to 10min while polling the server for async-task
completion. These operations are expected to finish within ~1 minute;
the long ceilings mostly hurt agents, whose harness kills the command on
timeout while the server-side operation keeps running with no handle to
re-query — especially risky for the irreversible recovery-apply.
Cap all three pollUntil ceilings at 2 minutes (polling interval
unchanged). Stuck operations now surface the retryable network/timeout
envelope after 2min instead of hanging for 10-30min.
* fix(plugin): create temp dir in project path to avoid cross-filesystem EXDEV on Rename (#1683)
pluginInstallLocal used os.MkdirTemp("") which creates the temp
directory on the system temp partition. On Windows (and some
Linux/macOS setups), the temp partition is on a different filesystem
from the project directory, causing os.Rename to fail with EXDEV.
Use projectPath as the temp dir parent so it is always on the same
filesystem as node_modules.
* fix(plugin): improve --help Tips with local-command hint and update semantics (#1691)
- Add "Run in project root; does NOT take --app-id" to all plugin Tips
- Clarify install command also supports update (install or update to latest/specific version)
- Clarify batch install reads from package.json actionPlugins
---------
Co-authored-by: 陈兴炀 <chenxingyang.1019@bytedance.com>
Co-authored-by: raistlin042 <lvxinsheng@bytedance.com>
Co-authored-by: anngo-nk <anguohui@bytedance.com>
Co-authored-by: zhangli <zhangli.268@bytedance.com>
Companion to commit 9fa73312 (transaction-id) and 6ca35b06
(history-version-id): the two flag tables in
skills/lark-sheets/references/lark-sheets-history.md still showed
'optional' even though the canonical contract — and shortcuts/sheets/data/
flag-defs.json — already moved to 'required'. The earlier syncs only
picked up the data file from spec; the skill markdown drift slipped
through. Pull in the spec-side regenerated reference (ee/sheet-skill-spec
@9ca814d) so the human-readable doc matches the wire contract.
Companion to commit 6ca35b06: same gating model now applies to both history
receipts.
- shortcuts/sheets/lark_sheet_history_revert.go: transactionIDFlag.Required=true.
Validate keeps a trim/empty-string guard for '--transaction-id ""'.
- shortcuts/sheets/data/flag-defs.json: +history-revert-status --transaction-id
required: optional -> required (synced from sheet-skill-spec @9ca814d).
- shortcuts/sheets/flag_defs_gen.go: regenerated.
- shortcuts/sheets/lark_sheet_history_test.go:
TestHistoryRevert_MissingRequiredFlag/+history-revert-status moved to the
cobra "required flag(s)" text contract (the test rig invokes the shortcut
via cmd.Execute, which sees the raw cobra error directly without the
dispatcher's typed wrap). Drop now-unused `errors` and `errs` imports.
Validation:
- go test ./shortcuts/sheets/... PASS (sheets + backward)
- TestFlagsFor_EveryRegisteredCommandHasDefs: PASS
- TestFlagDefsGen_MatchesJSON: PASS
- TestHistoryRevert_MissingRequiredFlag (both subtests): PASS
Two issues surfaced during MR !37 review:
1) +history-revert --history-version-id requiredness was set as
"optional" in the spec table (BE-2 fix dc5fe0ea) so cobra wouldn't
block before Validate. Per upstream review the flag should be
required-by-cobra so the user gets the standard "required flag(s)"
gate immediately and the runtime contract matches the JSON shape.
- shortcuts/sheets/lark_sheet_history_revert.go: historyVersionIDFlag
now sets Required: true. Validate keeps a trim/empty-string guard
so '--history-version-id ""' still fails as a typed
*errs.ValidationError (cobra accepts empty strings as "set").
- shortcuts/sheets/data/flag-defs.json: +history-revert
--history-version-id required: optional -> required.
- shortcuts/sheets/flag_defs_gen.go: regenerated.
- shortcuts/sheets/lark_sheet_history_test.go:
TestHistoryRevert_MissingRequiredFlag split into per-shortcut
subtests; +history-revert asserts cobra's "required flag(s)"
contract (raw err — the test rig calls cmd.Execute directly so it
doesn't see the cmd dispatcher's typed envelope wrap);
+history-revert-status keeps the typed *errs.ValidationError
contract (its --transaction-id stays cobra-optional + Validate-enforced).
2) max-cells safety cap was accidentally rewritten from 200000 to
50000 by the last sync from sheet-skill-spec (the spec canonical
side fell out of date — fixed separately on the spec MR follow-up).
Restore desc: "Safety cap; default 200000" / default: "200000" so
+cells-get / +csv-get keep the documented cap.
Validation:
- go test ./shortcuts/sheets/... PASS
- TestHistoryRevert_MissingRequiredFlag (both subtests) PASS
- TestHistoryShortcuts_DryRun (incl. +history-list pagination case) PASS
- TestFlagsFor_EveryRegisteredCommandHasDefs PASS
- TestFlagDefsGen_MatchesJSON PASS
Spec follow-up sheet-history-revert: thread the history_list pagination
contract through the +history-list shortcut.
- shortcuts/sheets/lark_sheet_history_list.go:
+ --end-version (int, optional). Mapped to the tool input's `end_version`
only when explicitly set (so the server treats absence as
"first page / latest"), via runtime.Changed / runtime.Int (matches the
+formula-verify --max-locations precedent).
+ Tip: pass next_end_version from the response on the next call;
capture exits the pagination loop when the server omits the field.
- shortcuts/sheets/lark_sheet_history_test.go: + dry-run case asserting
--end-version 12345 lands as input.end_version=12345 (post-JSON
unmarshal float64).
- skills/lark-sheets/references/lark-sheets-history.md: synced from
ee/sheet-skill-spec (commit 39c6b61). Adds the "倒序分页" caveat row +
--end-version flag + pagination Examples line. Drops the internal
MajorHistory.Version implementation detail per spec follow-up.
- shortcuts/sheets/data/flag-defs.json: synced from spec (+history-list
+--end-version int optional).
- shortcuts/sheets/flag_defs_gen.go: regenerated via
`go generate ./shortcuts/sheets/...`.
Companion changes:
- ee/sheet-skill-spec MR !37: spec-tables + tool-schemas pagination
contract (commits 09e8604, 39c6b61).
- ee/sheet-facade-agg MR !1028: history_list tool plumbs end_version,
emits next_end_version + has_more (omitted at earliest page),
defaults PageSize=20 to datarpc.
Validation:
- go build ./shortcuts/sheets/... PASS
- go test ./shortcuts/sheets/... PASS (sheets + backward)
- TestHistoryShortcuts_DryRun (5 cases incl. new --end-version case): PASS
- TestHistoryRevert_MissingRequiredFlag: PASS
- TestFlagsFor_EveryRegisteredCommandHasDefs: PASS
- TestFlagDefsGen_MatchesJSON: PASS
Mirror the upstream BE-2 fix in canonical-spec/references/lark_sheet_history/
cli-reference.md: +history-revert-status now uses --transaction-id (taken from
the async receipt returned by +history-revert), and +history-revert's
--history-version-id flips required→optional (Validate enforces requiredness
at runtime).
This file is the only history-only delta from the upstream sheet-skill-spec
sync; the rest of skills/lark-sheets/ stays on the cli's newer baseline
(/wiki/ URL support, +cells-set-image / +float-image-create, etc.) to match
commit 8ae516db's history-only mirror policy.
Spec source companion change: feat/sheet-history-revert in
ee/sheet-skill-spec, canonical-spec/{tool-shortcut-map.json,references/
lark_sheet_history/cli-reference.md}.