Commit Graph

4 Commits

Author SHA1 Message Date
raistlin042
36ff632a13 fix(apps): update miaoda scopes after platform consolidation (#1127)
妙搭/spark consolidated the apps domain onto spark:app:read / spark:app:write.
The standalone spark:app:publish and spark:app.access_scope:* scopes are retired.

- +html-publish:      spark:app:publish            -> spark:app:write
- +access-scope-get:  spark:app.access_scope:read  -> spark:app:read
- +access-scope-set:  spark:app.access_scope:write -> spark:app:write

Verified against the official docs for upload_html_code_and_release,
get_app_visibility and update_app_visibility. +create/+update/+list were
already correct (spark:app:write / spark:app:read).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 19:51:59 +08:00
raistlin042
e93e2a98e1 feat(apps): replace +html-publish cwd hard-reject with credential-file scan (#1072)
* feat(apps): replace +html-publish cwd hard-reject with credential-file scan

The previous --path == "." block was a coarse heuristic: it caught the
common foot-gun of publishing a repo root, but also rejected legitimate
clean cwds, and let a ./dist with a forgotten .env ship the secret
through anyway (the sensitive-paths scanner was advisory and never ran
on the Execute path).

Move the gate from path shape to path content:

- Validate now walks --path candidates and rejects publishes that
  include well-known credential files (.env / .env.* / .npmrc / .netrc
  / .git-credentials / .aws/credentials / .gcloud/credentials* /
  .docker/config.json / .kube/config). Living in Validate (not DryRun)
  means dry-run returns non-zero on hit too, so the dry-run preview
  matches Execute.
- Narrow the credential pattern set. .git/, SSH private keys, *.pem
  and *.key are out of scope -- they're not env-token files and the
  false-positive rate (public certs, docs about key formats) is high.
- Add --allow-sensitive as the escape hatch for legitimate cases
  (e.g. a docs site shipping .env.example on purpose). DryRun surfaces
  the waived list in sensitive_waived so the caller can relay it.
- Drop the cwd defense-in-depth in runHTMLPublish. A clean cwd is now
  a valid publish target.

The lark-apps skill and the html-publish reference are updated to
describe the new gate, the override flag, and the patterns now
explicitly out of scope.

* feat(apps): drop .gcloud/* from credential-file scan

The .gcloud/credentials pattern matched a non-existent path: gcloud's
actual config dir is ~/.config/gcloud/ (XDG-based), and the real
credential files there are credentials.db / access_tokens.db /
application_default_credentials.json -- none of which would land under
a .gcloud/ segment in a publish payload.

Drop the rule rather than fix it: the realistic gcloud foot-gun would
require recognizing the .config/gcloud/* tree by file basename, which
is a broader change than the targeted env/cred scan in this PR. The
remaining 7 patterns (.env / .env.* / .npmrc / .netrc /
.git-credentials / .aws/credentials / .docker/config.json /
.kube/config) cover the common Node/Python/CLI-tooling foot-guns.

* fix(apps): close credential-scan bypass when --path is the parent dir itself

isSensitiveRelPath anchors cloud-SDK matchers on adjacent parent/file
segments (.aws/credentials, .docker/config.json, .kube/config), but
walker strips that parent via filepath.Rel when --path is the conventional
parent dir (e.g. ./.aws), yielding a bare RelPath="credentials" that
slipped through silently. Same bypass for the single-file form
--path ./.aws/credentials (walker sets RelPath = Base(rootPath)).

Wrap the scan in isSensitiveCandidate: keep the fast RelPath scan, and
on miss fall back to filepath.Abs(AbsPath) so the parent segment is
visible again. isSensitiveRelPath itself is unchanged; existing tests
still pin its pure-function contract.

* fix(apps): drop filepath.Abs from sensitive scan to satisfy forbidigo lint

The previous fix called filepath.Abs(c.AbsPath) — banned by the repo's
forbidigo rule because shortcuts must not reach into the filesystem for
path resolution.

Reframe the same fix without fs access: re-prepend the root's basename
(or, for the single-file form, the parent dir's basename of rootPath)
to RelPath and re-scan only the parent-anchored credential pairs
(.aws/credentials, .docker/config.json, .kube/config). Leaf matchers
(.env / .npmrc / ...) stay scoped to RelPath — incidentally closing a
latent false-positive where --path /home/alice/.env/dist would have
flagged every file under it just because .env appeared in the
absolute path.
2026-05-25 23:24:40 +08:00
raistlin042
0dda56914d fix(apps): read app object from data.app for +create and +update (#1087)
* fix(apps): read app object from data.app for +create and +update

The Miaoda OpenAPI returns the application object nested under
data.app for both POST /apps and PATCH /apps/{appId}. The CLI text
helper was reading common.GetString(data, "app_id"), which yields an
empty string against the wire format -- so `lark-cli apps +create
--format pretty` printed `created: ` with no ID.

Navigate the new nested path via GetString(data, "app", "app_id") for
both create and update. Update unit-test mocks to wrap the response
under `app`. Refresh the lark-apps skill references (example response
shape + jq paths) so agents reading them follow the right path.

Wire format is passed through to the user's JSON envelope untouched
-- no unwrapping in CLI. Consumers reading the response should use
.data.app.app_id.

The GET /apps list endpoint is unchanged: per the design doc its
items[] are flat objects, no wrapper.

* docs(apps): add required --app-type HTML to scenario 2 snippet

The "用户没有 app_id" snippet in lark-apps-html-publish.md was missing
the required --app-type flag, so copy-pasting it triggered Validate
("--app-type is required") and left $APP empty -- the following
+html-publish then failed with --app-id "". Bring the snippet in line
with every other apps +create example in the skill.

* docs(apps): simplify auth-recovery rule to error.type == missing_scope

Every apps shortcut declares Scopes, so the precheck path in
shortcuts/common/runner.go:825 is always the one that fires on scope
violations and the envelope's error.type is the stable discriminator.
Drop the keyword-sniffing of error.hint, the chain explanation, and the
bot caveat — they all reduce to one boolean: error.type == "missing_scope"
→ run `lark-cli auth login --domain apps`.

Also collapse the corresponding bullet in 快速决策 to point at this rule.
2026-05-25 23:16:30 +08:00
raistlin042
6cea6c9af0 feat(apps): add miaoda apps domain (6 shortcuts + dry-run e2e) (#1002)
Adds the apps domain to lark-cli for managing Miaoda (妙搭) applications: 6 shortcuts covering the full lifecycle (+create / +update / +list / +access-scope-set / +access-scope-get / +html-publish). Aligned with the OAPI v2 design — app_type enum (currently HTML), string scope enum (All / Tenant / Range), cursor pagination, in-memory tar.gz multipart publish flow. Namespace registered at /open-apis/spark/v1/ with spark:app.* scopes.

---------

Co-authored-by: wangjiangwen-gif <286006750+wangjiangwen-gif@users.noreply.github.com>
2026-05-21 20:30:42 +08:00