@lark-apaas/coding-miaoda-sandbox-skills 0.1.0-dev.ec88bb5 → 0.1.0-dev.f3f0e48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/miaoda/ai-data-processing/SKILL.md +4 -1
- package/miaoda/animation-skill/SKILL.md +348 -0
- package/miaoda/authz-cli/SKILL.md +1 -0
- package/miaoda/charts-skill/SKILL.md +264 -0
- package/miaoda/creative-to-fullstack/SKILL.md +64 -0
- package/miaoda/data-analysis/SKILL.md +151 -0
- package/miaoda/data-analysis/references/json-output-specification.md +277 -0
- package/miaoda/data-analysis/references/post-analysis-guide.md +77 -0
- package/miaoda/data-analysis/references/python-analysis-reference.md +272 -0
- package/miaoda/data-analysis/references/tmp-file-management-guide.md +100 -0
- package/miaoda/debug-investigation/SKILL.md +35 -23
- package/miaoda/extract-json-schema/SKILL.md +147 -0
- package/miaoda/feishu/SKILL.md +4 -4
- package/miaoda/forms-skill/SKILL.md +46 -4
- package/miaoda/lark-apps/SKILL.md +37 -0
- package/miaoda/lark-apps/references/openapi-key.md +80 -0
- package/miaoda/lark-apps-authz/SKILL.md +292 -0
- package/miaoda/lark-apps-authz/references/permission-points.md +39 -0
- package/miaoda/lark-apps-authz/references/role.md +122 -0
- package/miaoda/lark-apps-db/SKILL.md +227 -0
- package/miaoda/lark-apps-db/references/full-reference.md +424 -0
- package/miaoda/lark-apps-file/SKILL.md +216 -0
- package/miaoda/lark-apps-ops/SKILL.md +67 -0
- package/miaoda/lark-apps-ops/references/lark-apps-access-scope-get.md +30 -0
- package/miaoda/lark-apps-ops/references/lark-apps-access-scope-set.md +40 -0
- package/miaoda/lark-apps-ops/references/lark-apps-cache.md +62 -0
- package/miaoda/lark-apps-ops/references/lark-apps-env.md +46 -0
- package/miaoda/lark-apps-ops/references/lark-apps-export.md +46 -0
- package/miaoda/lark-apps-ops/references/lark-apps-local-dev.md +26 -0
- package/miaoda/lark-apps-ops/references/lark-apps-mcp.md +25 -0
- package/miaoda/lark-apps-ops/references/lark-apps-member.md +93 -0
- package/miaoda/lark-apps-ops/references/lark-apps-observability.md +46 -0
- package/miaoda/lark-apps-ops/references/lark-apps-plugin-install.md +36 -0
- package/miaoda/lark-apps-ops/references/lark-apps-plugin-list.md +23 -0
- package/miaoda/lark-apps-ops/references/lark-apps-plugin-uninstall.md +25 -0
- package/miaoda/lark-apps-ops/references/lark-apps-release-create.md +37 -0
- package/miaoda/lark-apps-ops/references/lark-apps-release-get.md +59 -0
- package/miaoda/lark-apps-ops/references/lark-apps-release-list.md +31 -0
- package/miaoda/lark-apps-ops/references/lark-apps-update.md +30 -0
- package/miaoda/lark-apps-ops/references/lark-apps-user-id-convert.md +63 -0
- package/miaoda/lark-apps-ops/references/openapi-key.md +80 -0
- package/miaoda/lark-design-prototype/DESIGN.md +603 -0
- package/miaoda/lark-design-prototype/SKILL.md +85 -0
- package/miaoda/lark-design-prototype/references/assets/card-illustration-library.md +113 -0
- package/miaoda/lark-design-prototype/references/case-matching.md +53 -0
- package/miaoda/lark-design-prototype/references/cases/conversational-ai-home.md +27 -0
- package/miaoda/lark-design-prototype/references/cases/data-table.md +30 -0
- package/miaoda/lark-design-prototype/references/cases/official-home.md +26 -0
- package/miaoda/lark-design-prototype/references/cases/workspace-home.md +34 -0
- package/miaoda/lark-design-prototype/references/color-roles.md +163 -0
- package/miaoda/lark-design-prototype/references/component-selection.md +134 -0
- package/miaoda/lark-design-prototype/references/design-quality-checklist.md +156 -0
- package/miaoda/lark-design-prototype/references/form-shell-patterns.md +77 -0
- package/miaoda/lark-design-prototype/references/icon-semantics.md +237 -0
- package/miaoda/lark-design-prototype/references/layout-interaction.md +164 -0
- package/miaoda/lark-design-prototype/references/page-contract.md +281 -0
- package/miaoda/lark-design-prototype/references/product-patterns.md +93 -0
- package/miaoda/lark-design-prototype/references/prompt-expansion.md +107 -0
- package/miaoda/lark-design-prototype/references/restoration-traps.md +113 -0
- package/miaoda/lark-design-prototype/references/token-semantics.md +112 -0
- package/miaoda/lark-design-prototype/references/visual-brief.md +125 -0
- package/miaoda/lark-design-prototype/references/visual-style-prompts.md +61 -0
- package/miaoda/lark-design-prototype/scripts/icon-query.mjs +272 -0
- package/miaoda/lark-design-prototype/scripts/token-query.mjs +76 -0
- package/miaoda/lark-design-prototype/scripts/verify-static-html.mjs +117 -0
- package/miaoda/miaoda-file/SKILL.md +1 -0
- package/miaoda/miaoda-sql/SKILL.md +21 -2
- package/miaoda/performance-review/SKILL.md +144 -0
- package/miaoda/performance-review/references/business-analyzer.md +139 -0
- package/miaoda/performance-review/references/examples.md +107 -0
- package/miaoda/semantic-search/SKILL.md +6 -4
- package/miaoda/table-skill/SKILL.md +2 -0
- package/{shared → miaoda}/testing-guide/SKILL.md +119 -13
- package/miaoda-design/lark-apps-comment/SKILL.md +119 -0
- package/miaoda-design/lark-apps-ops/SKILL.md +47 -0
- package/miaoda-design/lark-apps-ops/references/lark-apps-release-create.md +52 -0
- package/miaoda-design/lark-apps-ops/references/lark-apps-release-get.md +59 -0
- package/miaoda-design/lark-apps-ops/references/lark-apps-release-list.md +31 -0
- package/miaoda-design/lark-apps-ops/references/lark-apps-update.md +33 -0
- package/{shared → miaoda-modern}/charts-skill/SKILL.md +1 -1
- package/miaoda-modern/debug-investigation/SKILL.md +1 -1
- package/miaoda-modern/forms-skill/SKILL.md +70 -7
- package/{shared → miaoda-modern}/lark-apps/SKILL.md +5 -5
- package/miaoda-modern/lark-apps/references/openapi-key.md +80 -0
- package/miaoda-modern/lark-apps-ops/SKILL.md +67 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-access-scope-get.md +30 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-access-scope-set.md +40 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-cache.md +62 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-env.md +46 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-export.md +46 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-local-dev.md +26 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-mcp.md +25 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-member.md +93 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-observability.md +46 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-plugin-install.md +36 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-plugin-list.md +23 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-plugin-uninstall.md +25 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-release-create.md +37 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-release-get.md +59 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-release-list.md +31 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-update.md +30 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-user-id-convert.md +63 -0
- package/{shared/lark-apps → miaoda-modern/lark-apps-ops}/references/openapi-key.md +3 -3
- package/miaoda-modern/lark-design-prototype/DESIGN.md +603 -0
- package/miaoda-modern/lark-design-prototype/SKILL.md +85 -0
- package/miaoda-modern/lark-design-prototype/references/assets/card-illustration-library.md +113 -0
- package/miaoda-modern/lark-design-prototype/references/case-matching.md +53 -0
- package/miaoda-modern/lark-design-prototype/references/cases/conversational-ai-home.md +27 -0
- package/miaoda-modern/lark-design-prototype/references/cases/data-table.md +30 -0
- package/miaoda-modern/lark-design-prototype/references/cases/official-home.md +26 -0
- package/miaoda-modern/lark-design-prototype/references/cases/workspace-home.md +34 -0
- package/miaoda-modern/lark-design-prototype/references/color-roles.md +163 -0
- package/miaoda-modern/lark-design-prototype/references/component-selection.md +134 -0
- package/miaoda-modern/lark-design-prototype/references/design-quality-checklist.md +156 -0
- package/miaoda-modern/lark-design-prototype/references/form-shell-patterns.md +77 -0
- package/miaoda-modern/lark-design-prototype/references/icon-semantics.md +237 -0
- package/miaoda-modern/lark-design-prototype/references/layout-interaction.md +164 -0
- package/miaoda-modern/lark-design-prototype/references/page-contract.md +281 -0
- package/miaoda-modern/lark-design-prototype/references/product-patterns.md +93 -0
- package/miaoda-modern/lark-design-prototype/references/prompt-expansion.md +107 -0
- package/miaoda-modern/lark-design-prototype/references/restoration-traps.md +113 -0
- package/miaoda-modern/lark-design-prototype/references/token-semantics.md +112 -0
- package/miaoda-modern/lark-design-prototype/references/visual-brief.md +125 -0
- package/miaoda-modern/lark-design-prototype/references/visual-style-prompts.md +61 -0
- package/miaoda-modern/lark-design-prototype/scripts/icon-query.mjs +272 -0
- package/miaoda-modern/lark-design-prototype/scripts/token-query.mjs +76 -0
- package/miaoda-modern/lark-design-prototype/scripts/verify-static-html.mjs +117 -0
- package/miaoda-modern/memory/SKILL.md +86 -0
- package/{shared → miaoda-modern}/performance-review/SKILL.md +3 -3
- package/miaoda-modern/reviewer-usage/SKILL.md +113 -0
- package/package.json +1 -1
- package/shared/attachment/SKILL.md +5 -1
- package/shared/lark-cli/SKILL.md +221 -0
- package/shared/lark-cli/lark-base/README.md +61 -0
- package/shared/lark-cli/lark-base/references/lark-base-commands.md +123 -0
- package/shared/lark-cli/lark-calendar/README.md +158 -0
- package/shared/lark-cli/lark-calendar/references/lark-calendar-meeting.md +30 -0
- package/shared/lark-cli/lark-calendar/references/lark-calendar-room-find.md +108 -0
- package/shared/lark-cli/lark-calendar/references/lark-calendar-suggestion.md +120 -0
- package/shared/lark-cli/lark-contact/README.md +35 -0
- package/shared/lark-cli/lark-contact/references/lark-contact-get-user.md +13 -0
- package/shared/lark-cli/lark-contact/references/lark-contact-search-user.md +121 -0
- package/shared/lark-cli/lark-doc/README.md +68 -0
- package/shared/lark-cli/lark-doc/references/lark-doc-fetch.md +138 -0
- package/shared/lark-cli/lark-doc/references/lark-doc-history.md +61 -0
- package/shared/lark-cli/lark-drive/README.md +158 -0
- package/shared/lark-cli/lark-drive/references/lark-drive-batch-query-comments.md +44 -0
- package/shared/lark-cli/lark-drive/references/lark-drive-files-list.md +183 -0
- package/shared/lark-cli/lark-drive/references/lark-drive-list-replies.md +49 -0
- package/shared/lark-cli/lark-im/README.md +70 -0
- package/shared/lark-cli/lark-im/references/lark-im-chat-list.md +140 -0
- package/shared/lark-cli/lark-im/references/lark-im-chat-members-list.md +84 -0
- package/shared/lark-cli/lark-im/references/lark-im-chat-search.md +135 -0
- package/shared/lark-cli/lark-im/references/lark-im-reactions.md +232 -0
- package/shared/lark-cli/lark-minutes/README.md +51 -0
- package/shared/lark-cli/lark-minutes/references/lark-minutes-download.md +130 -0
- package/shared/lark-cli/lark-sheets/README.md +174 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-changeset.md +105 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-chart.md +46 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-conditional-format.md +42 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-filter-view.md +51 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-filter.md +42 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-float-image.md +43 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-formula-verify.md +64 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-history.md +70 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-pivot-table.md +44 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-read-data.md +287 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-search-replace.md +67 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-sheet-structure.md +52 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-sparkline.md +47 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-workbook.md +69 -0
- package/shared/lark-cli/lark-sheets/scripts/lark_detect_subtables.py +596 -0
- package/shared/lark-cli/lark-sheets/scripts/lark_inspect_workbook.py +193 -0
- package/shared/lark-cli/lark-sheets/scripts/lark_profile_table.py +616 -0
- package/shared/lark-cli/lark-sheets/scripts/lark_sheet_range.py +176 -0
- package/shared/lark-cli/lark-sheets/scripts/lark_sheet_read_cli.py +221 -0
- package/shared/lark-cli/lark-sheets/scripts/sheets_df.py +50 -0
- package/shared/lark-cli/lark-slides/README.md +87 -0
- package/shared/lark-cli/lark-slides/references/lark-slides-history.md +117 -0
- package/shared/lark-cli/lark-slides/references/lark-slides-xml-presentation-slide-get.md +108 -0
- package/shared/lark-cli/lark-slides/references/lark-slides-xml-presentations-get.md +77 -0
- package/shared/lark-cli/lark-task/README.md +93 -0
- package/shared/lark-cli/lark-task/references/lark-task-get-my-tasks.md +57 -0
- package/shared/lark-cli/lark-task/references/lark-task-get-related-tasks.md +49 -0
- package/shared/lark-cli/lark-task/references/lark-task-search.md +36 -0
- package/shared/lark-cli/lark-task/references/lark-task-tasklist-search.md +35 -0
- package/shared/lark-cli/lark-vc/README.md +40 -0
- package/shared/lark-cli/lark-vc/references/lark-vc-recording.md +31 -0
- package/shared/lark-cli/lark-whiteboard/README.md +34 -0
- package/shared/lark-cli/lark-whiteboard/references/lark-whiteboard-export.md +59 -0
- package/shared/lark-cli/lark-wiki/README.md +50 -0
- package/shared/lark-cli/lark-wiki/references/lark-wiki-node-get.md +70 -0
- package/shared/lark-cli/lark-wiki/references/lark-wiki-node-list.md +95 -0
- package/shared/lark-cli/lark-wiki/references/lark-wiki-space-list.md +68 -0
- package/miaoda-design/attachment/SKILL.md +0 -58
- package/shared/dev-channel-probe/SKILL.md +0 -40
- /package/{shared → miaoda}/memory/SKILL.md +0 -0
- /package/{shared → miaoda}/reviewer-usage/SKILL.md +0 -0
- /package/{shared → miaoda-modern}/animation-skill/SKILL.md +0 -0
- /package/{shared → miaoda-modern}/data-analysis/SKILL.md +0 -0
- /package/{shared → miaoda-modern}/data-analysis/references/json-output-specification.md +0 -0
- /package/{shared → miaoda-modern}/data-analysis/references/post-analysis-guide.md +0 -0
- /package/{shared → miaoda-modern}/data-analysis/references/python-analysis-reference.md +0 -0
- /package/{shared → miaoda-modern}/data-analysis/references/tmp-file-management-guide.md +0 -0
- /package/{shared → miaoda-modern}/extract-json-schema/SKILL.md +0 -0
- /package/{shared → miaoda-modern}/performance-review/references/business-analyzer.md +0 -0
- /package/{shared → miaoda-modern}/performance-review/references/examples.md +0 -0
|
@@ -13,6 +13,12 @@ Shadcn Form + React Hook Form + Zod 表单开发。
|
|
|
13
13
|
- 所有字段必须有默认值
|
|
14
14
|
- 必须用 Shadcn 组件,禁止原生 input
|
|
15
15
|
- 同行 FormField 必须等宽
|
|
16
|
+
- 每个控件都要有能读出来的字段名(读屏和自动化验收都按它找控件):FormField 内用 `FormLabel` + `FormControl`,id 会自动关联;FormField 外的筛选、搜索控件用 `<Label htmlFor="x">` 配控件 `id="x"`,没有可见标签时加 `aria-label`。不要只靠 placeholder 或当前选中值表达字段含义
|
|
17
|
+
- 必填星号加 `aria-hidden="true"`,别让 `*` 混进字段名
|
|
18
|
+
- 字段校验错误用 `<FormMessage />` 显示在字段下方;toast 只用于提交结果(成功 / 接口失败),不要用 toast 提示「请输入 xx」
|
|
19
|
+
- 日期字段用 `Popover` + `Calendar`,`FormControl` 包住触发按钮,禁止 `input[type="date"]`
|
|
20
|
+
- 自定义输入组件(富文本等)也放进 `FormControl`,并把 `id`、`aria-*` 透传到真正可编辑的元素上
|
|
21
|
+
- 表单提交到必填 API/DTO/Request/interface 前,先读目标 shared/server 类型,在 `handleSubmit` 回调里用 `data` 逐字段构造 typed request(见 Patterns);不要整体传 `data`、`schema.parse(data)` 或 `.required().parse(data)`,也不要用 `any`/`as` 绕过 TS2322。修完后跑 LSP 或 `typecheck`。
|
|
16
22
|
|
|
17
23
|
---
|
|
18
24
|
|
|
@@ -48,14 +54,14 @@ export function StudentForm() {
|
|
|
48
54
|
<div className="flex flex-wrap gap-4">
|
|
49
55
|
<FormField control={form.control} name="name" render={({ field }) => (
|
|
50
56
|
<FormItem className="flex-1">
|
|
51
|
-
<FormLabel>姓名 <span className="text-destructive">*</span></FormLabel>
|
|
57
|
+
<FormLabel>姓名 <span aria-hidden="true" className="text-destructive">*</span></FormLabel>
|
|
52
58
|
<FormControl><Input placeholder="请输入姓名" {...field} /></FormControl>
|
|
53
59
|
<FormMessage />
|
|
54
60
|
</FormItem>
|
|
55
61
|
)} />
|
|
56
62
|
<FormField control={form.control} name="age" render={({ field }) => (
|
|
57
63
|
<FormItem className="flex-1">
|
|
58
|
-
<FormLabel>年龄 <span className="text-destructive">*</span></FormLabel>
|
|
64
|
+
<FormLabel>年龄 <span aria-hidden="true" className="text-destructive">*</span></FormLabel>
|
|
59
65
|
<FormControl><Input type="number" {...field} /></FormControl>
|
|
60
66
|
<FormMessage />
|
|
61
67
|
</FormItem>
|
|
@@ -63,7 +69,7 @@ export function StudentForm() {
|
|
|
63
69
|
</div>
|
|
64
70
|
<FormField control={form.control} name="grade" render={({ field }) => (
|
|
65
71
|
<FormItem>
|
|
66
|
-
<FormLabel>年级 <span className="text-destructive">*</span></FormLabel>
|
|
72
|
+
<FormLabel>年级 <span aria-hidden="true" className="text-destructive">*</span></FormLabel>
|
|
67
73
|
<Select onValueChange={field.onChange} defaultValue={field.value}>
|
|
68
74
|
<FormControl><SelectTrigger><SelectValue placeholder="请选择" /></SelectTrigger></FormControl>
|
|
69
75
|
<SelectContent>
|
|
@@ -98,7 +104,43 @@ const form = useForm<FormData>({ resolver: zodResolver(schema), defaultValues: {
|
|
|
98
104
|
</div>
|
|
99
105
|
|
|
100
106
|
// 必填标记
|
|
101
|
-
<FormLabel>字段 <span className="text-destructive">*</span></FormLabel>
|
|
107
|
+
<FormLabel>字段 <span aria-hidden="true" className="text-destructive">*</span></FormLabel>
|
|
108
|
+
|
|
109
|
+
// 表单外的筛选 / 搜索控件:可见标签用 htmlFor + id 关联;没有可见标签必须加 aria-label
|
|
110
|
+
<Label htmlFor="status-filter">状态</Label>
|
|
111
|
+
<Select value={status} onValueChange={setStatus}>
|
|
112
|
+
<SelectTrigger id="status-filter"><SelectValue placeholder="全部状态" /></SelectTrigger>
|
|
113
|
+
<SelectContent>{/* SelectItem ... */}</SelectContent>
|
|
114
|
+
</Select>
|
|
115
|
+
<Input aria-label="搜索姓名或职位" placeholder="搜索姓名或职位" value={keyword} onChange={(e) => setKeyword(e.target.value)} />
|
|
116
|
+
|
|
117
|
+
// 日期:Popover + Calendar,FormControl 包住触发按钮,label 才能关联到它
|
|
118
|
+
<FormField control={form.control} name="dueDate" render={({ field }) => (
|
|
119
|
+
<FormItem>
|
|
120
|
+
<FormLabel>截止日期</FormLabel>
|
|
121
|
+
<Popover>
|
|
122
|
+
<PopoverTrigger asChild>
|
|
123
|
+
<FormControl>
|
|
124
|
+
<Button variant="outline" className="w-full justify-start font-normal">
|
|
125
|
+
{field.value ? dayjs(field.value).format("YYYY-MM-DD") : "请选择日期"}
|
|
126
|
+
</Button>
|
|
127
|
+
</FormControl>
|
|
128
|
+
</PopoverTrigger>
|
|
129
|
+
<PopoverContent className="w-auto p-0" align="start">
|
|
130
|
+
<Calendar mode="single" selected={field.value} onSelect={field.onChange} />
|
|
131
|
+
</PopoverContent>
|
|
132
|
+
</Popover>
|
|
133
|
+
<FormMessage />
|
|
134
|
+
</FormItem>
|
|
135
|
+
)} />
|
|
136
|
+
|
|
137
|
+
// 必填 Request/DTO 桥接:zodResolver 负责运行时校验,DTO 边界负责静态类型匹配。
|
|
138
|
+
// 用 handleSubmit 回调的 data,不要用 getValues(拿到的是 coerce 前的原始值)。
|
|
139
|
+
import type { SaveRequest } from "@/shared/api";
|
|
140
|
+
form.handleSubmit(async (data) => {
|
|
141
|
+
const request: SaveRequest = { field: data.field };
|
|
142
|
+
await api.save(request);
|
|
143
|
+
});
|
|
102
144
|
|
|
103
145
|
// 调试
|
|
104
146
|
logger.info("errors:", form.formState.errors);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lark-apps
|
|
3
|
+
description: "在妙搭沙箱里用 lark-cli 操作【当前这个已存在的】妙搭应用:开放 API Key。当用户要在沙箱里对当前应用做这些操作时使用(可用能力以本次打包的模块为准)。"
|
|
4
|
+
metadata:
|
|
5
|
+
requires:
|
|
6
|
+
bins: ["lark-cli"]
|
|
7
|
+
cliHelp: "lark-cli apps --help; lark-cli apps +<cmd> --help"
|
|
8
|
+
control-by-feature-ab: true
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# 妙搭应用 (apps) · 沙箱版
|
|
12
|
+
|
|
13
|
+
在妙搭沙箱里通过 `lark-cli` 操作**当前这个已存在的**妙搭应用。
|
|
14
|
+
|
|
15
|
+
## 沙箱约定(先读)
|
|
16
|
+
|
|
17
|
+
- **命令名**:一律 `lark-cli apps +<cmd>`;命令/flag 细节以 `--help` 为准。
|
|
18
|
+
- **应用已存在、app_id 走环境变量**:应用 id 在环境变量 `app_id` 里,命令需要 `--app-id` 时用 `--app-id "$app_id"`。
|
|
19
|
+
- **鉴权自动**:apps 域请求由运行环境自动打到 innerAPI 并注入鉴权头。**不要** `auth login` / `config init` / `--as`。
|
|
20
|
+
|
|
21
|
+
## 意图路由
|
|
22
|
+
|
|
23
|
+
| 用户意图 | 命令 | 详情 |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| 管理开放 API Key(列/查/建/改/启停/删/轮换) | `+openapi-key-list` / `+openapi-key-get` / `+openapi-key-create` / `+openapi-key-update` / `+openapi-key-enable` / `+openapi-key-disable` / `+openapi-key-delete` / `+openapi-key-reset` | [openapi-key](references/openapi-key.md) ⚠️ create/reset 密钥一次性可见;delete/reset 高风险 |
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
## 失败处理
|
|
29
|
+
命令失败时把 `error.hint` 转述给用户,别原样甩 envelope JSON。
|
|
30
|
+
|
|
31
|
+
## 高风险写操作审批(exit 10)
|
|
32
|
+
`risk: high-risk-write` 的命令不带 `--yes` 会 **exit 10** 并返回 `confirmation_required`。处理:
|
|
33
|
+
1. 识别 exit code=10 且 `error.type=="confirmation_required"`;
|
|
34
|
+
2. 把 `error.risk.action` + 关键参数给用户,明确"高风险",等显式同意;
|
|
35
|
+
3. 同意 → 原始 argv 末尾加 `--yes` 重试;拒绝 → 终止;
|
|
36
|
+
4. 想先看请求 → `--dry-run`(不触发门禁、不需 `--yes`)。
|
|
37
|
+
**绝不**看到 exit 10 就默认补 `--yes` 静默重试。
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# apps openapi-key 命令族(开放 API Key)
|
|
2
|
+
|
|
3
|
+
管理妙搭应用对外暴露的 HTTP API Key(`/openapi/**` 鉴权凭证)。命令事实以 `lark-cli apps +openapi-key-list --help`(各子命令同理)为准;本文件只记录 Agent 不看就会做错的领域规则。鉴权由沙箱运行环境自动注入(见 SKILL.md「鉴权自动」),命令无需也不要传身份参数。
|
|
4
|
+
|
|
5
|
+
## 命令路由
|
|
6
|
+
|
|
7
|
+
| 命令 | 用途 |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `+openapi-key-list` | 列出应用所有 API Key(脱敏) |
|
|
10
|
+
| `+openapi-key-get` | 查看单个 Key 详情(脱敏) |
|
|
11
|
+
| `+openapi-key-create` | 创建新 Key,**原始密钥一次性可见** |
|
|
12
|
+
| `+openapi-key-update` | 改名或改 config(不改 status) |
|
|
13
|
+
| `+openapi-key-enable` | 启用 Key(status→1) |
|
|
14
|
+
| `+openapi-key-disable` | 停用 Key(status→0),**泄露/疑似泄露优先用这个而非 delete** |
|
|
15
|
+
| `+openapi-key-delete` | 永久删除 Key(不可逆,高风险) |
|
|
16
|
+
| `+openapi-key-reset` | 轮换密钥(刷新原始 Key),**一次性可见**(高风险) |
|
|
17
|
+
|
|
18
|
+
命令均带 `--app-id "$app_id"`(当前沙箱应用),如:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
lark-cli apps +openapi-key-list --app-id "$app_id"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## 密钥红线(安全关键,务必遵守)
|
|
25
|
+
|
|
26
|
+
- `create` / `reset` 返回的**原始密钥仅一次性可见**:只在 `data.api_key`(顶层)随本次响应返回一次,同时 stderr 打印一次性提示(大意:此密钥仅显示一次、不被 lark-cli 保存,请立即复制到你自己的密钥管理器)。
|
|
27
|
+
- **绝不**把原始密钥写入 cache / config / recent / debug log / 错误信息,也不要在后续对话里回显完整密钥;只向用户转述一次并提示自行妥善保管。
|
|
28
|
+
- **密钥丢失不能找回**:`list` / `get` 不回显原始密钥。唯一恢复方式是 `+openapi-key-reset` 重新生成新密钥(旧密钥同时失效)。
|
|
29
|
+
|
|
30
|
+
## 脱敏口径
|
|
31
|
+
|
|
32
|
+
- `list` / `get` / `update` / `enable` / `disable`:返回结构里 **无** `api_key` 字段,只有 `key_preview`(格式:`****` + 原始密钥末 4 位,如 `****5f4a`)。
|
|
33
|
+
- `create` / `reset`:**仅** 在 `data.api_key`(顶层)返回原始密钥一次(见上「密钥红线」)。
|
|
34
|
+
|
|
35
|
+
## scope 结构与 CLI 表达
|
|
36
|
+
|
|
37
|
+
后端 `config.request_scope` 的真实结构(**snake_case**——Lark 开放网关 `/open-apis/` 对外契约约定;`api_key.thrift` 的 camelCase go.tag 是内部表示,OGW 已转成 snake_case):
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"allow_all": true,
|
|
42
|
+
"http_infos": [
|
|
43
|
+
{ "http_method": "GET", "http_path": "/openapi/some-path" }
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- `allow_all=true`:放开该应用所有 `/openapi/**` 路由;`http_infos` 此时忽略。
|
|
49
|
+
- `allow_all=false`:按 `http_infos` 逐条授权,每条需 `http_method`(大写)+ `http_path`(`/openapi/` 开头)。
|
|
50
|
+
|
|
51
|
+
CLI 提供三种互斥的 scope 表达方式:
|
|
52
|
+
|
|
53
|
+
| flag | 用途 | 备注 |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| `--scope-all` | `allow_all=true`,放开所有路由 | bool flag,显式传 `--scope-all=false` 也算"已设置" |
|
|
56
|
+
| `--scope-api 'METHOD /openapi/path'` | 逐条授权一个路由,可重复 | 路由从应用 `docs/openapi.json` 取 |
|
|
57
|
+
| `--scope '<raw request_scope JSON>'` | 高级逃生口,直传 request_scope JSON(snake_case) | CLI 只校验合法 JSON;`--scope` 与 `--scope-all`/`--scope-api` 互斥 |
|
|
58
|
+
|
|
59
|
+
### scope 值来源
|
|
60
|
+
|
|
61
|
+
妙搭应用的 `/openapi/**` 路由定义在应用仓库,并同步维护在 `docs/openapi.json`(`paths` 下每个 `"/openapi/..."` 条目 + HTTP 方法)。要授权哪些路由,读目标应用自己的 `docs/openapi.json`,取 `(method, path)` 对。CLI 本身不提供 API 路由发现功能(P1 规划中)。
|
|
62
|
+
|
|
63
|
+
## 高风险操作(delete / reset)
|
|
64
|
+
|
|
65
|
+
`delete` 和 `reset` 是高风险写操作(`high-risk-write`):缺 `--yes` 会 **exit 10**(`confirmation_required`),须按 SKILL.md 的 exit-10 审批协议先征得用户显式同意再补 `--yes`——**不要**自动补 `--yes`;不确定先 `--dry-run` 查看将执行的 HTTP 请求(不含密钥)。
|
|
66
|
+
|
|
67
|
+
- **泄露场景**:应优先 `+openapi-key-disable` 立即停用,而非 `+openapi-key-delete`——停用可随时 `+openapi-key-enable` 恢复,delete 不可逆。
|
|
68
|
+
|
|
69
|
+
## 典型决策场景
|
|
70
|
+
|
|
71
|
+
| 用户意图 | 正确操作 |
|
|
72
|
+
|---|---|
|
|
73
|
+
| "key 泄露了,先停掉" | `+openapi-key-disable`(不是 delete) |
|
|
74
|
+
| "key 丢了/忘了,再给我一个" | `+openapi-key-reset`(不是 create 新 key;reset 轮换密钥、保留原 key 配置) |
|
|
75
|
+
| "我的 key 密钥是什么" | 解释:list/get 不回显原始密钥,只能用 `+openapi-key-reset` 轮换 |
|
|
76
|
+
| "给应用创建一个有权限限制的 key" | `+openapi-key-create --name ... --scope-api 'GET /openapi/...'`(路由取自应用 `docs/openapi.json`) |
|
|
77
|
+
|
|
78
|
+
## 不在本 skill 范围
|
|
79
|
+
|
|
80
|
+
- OpenAPI spec 全量导出、实时日志 tail、Webhook 消费、多鉴权方式:本期不支持。
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lark-apps-authz
|
|
3
|
+
description: "Use when 在妙搭沙箱里用 `lark-cli apps +role-*` 管理【当前这个已存在的】妙搭应用的角色与角色成员、查询用户命中的角色,或用 `lark-cli apps +db-execute` 维护权限点位表(建表、预填、新增、更新、删除点位)。触发词:查询角色列表, 创建角色, 删除角色, 角色成员, 查询用户角色, 权限点位, 权限表, 新增点位, 更新点位, 删除点位, +role-, role-list, role-match-list. NOT for 编写权限控制代码——CanRole/@Can 编码用 authz-guide skill。"
|
|
4
|
+
metadata:
|
|
5
|
+
requires:
|
|
6
|
+
bins: ["lark-cli"]
|
|
7
|
+
cliHelp: "lark-cli apps --help; lark-cli apps +role-list --help(各 +role-* 子命令同理)"
|
|
8
|
+
control-by-feature-ab: true
|
|
9
|
+
unavailable-agents:
|
|
10
|
+
- AppInit
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# lark-apps-authz — 权限管理工具
|
|
14
|
+
|
|
15
|
+
Agent 在沙箱内直接执行的权限管理工具集,包含两部分能力:
|
|
16
|
+
|
|
17
|
+
- **角色管理**:通过 `lark-cli apps +role-*` 管理角色(查询、创建、更新、删除、成员管理、查询用户命中角色)。完整命令细节见 [references/role.md](references/role.md)
|
|
18
|
+
- **权限点位管理**:通过 `lark-cli apps +db-execute` 管理权限表和数据(建表、新增/更新/删除点位、管理映射)。SQL 执行通道与建表规范以 `lark-apps-db` skill 为准
|
|
19
|
+
|
|
20
|
+
## 沙箱约定(先读)
|
|
21
|
+
|
|
22
|
+
- **命令名**:一律 `lark-cli apps +role-*` / `lark-cli apps +db-execute`;命令/flag 细节以 `--help` 为准。
|
|
23
|
+
- **应用已存在、app_id 走环境变量**:应用 id 在环境变量 `app_id` 里,命令需要 `--app-id` 时用 `--app-id "$app_id"`,不需要自行获取、解析或选择。
|
|
24
|
+
- **鉴权自动**:apps 域请求由运行环境自动打到 innerAPI 并注入鉴权头。**不要** `auth login` / `config init` / `--as`。
|
|
25
|
+
- **失败处理**:命令失败时把 `error.hint` 转述给用户,别原样甩 envelope JSON。
|
|
26
|
+
|
|
27
|
+
### 高风险写操作审批(exit 10)
|
|
28
|
+
|
|
29
|
+
`+role-delete`、`+role-member-remove`(含 `--all`)等删除类操作属于高风险写:不带 `--yes` 会 **exit 10** 并返回 `confirmation_required`。处理:
|
|
30
|
+
|
|
31
|
+
1. 识别 exit code=10 且 `error.type=="confirmation_required"`;
|
|
32
|
+
2. 把 `error.risk.action` + 关键参数给用户,明确"高风险/不可逆",等显式同意;
|
|
33
|
+
3. 同意 → 原始 argv 末尾加 `--yes` 重试;拒绝 → 终止;
|
|
34
|
+
4. 想先看请求 → `--dry-run`(不触发门禁、不需 `--yes`)。
|
|
35
|
+
|
|
36
|
+
**绝不**看到 exit 10 就默认补 `--yes` 静默重试。
|
|
37
|
+
|
|
38
|
+
## 工具边界
|
|
39
|
+
|
|
40
|
+
| 场景 | 正确做法 |
|
|
41
|
+
|------|----------|
|
|
42
|
+
| Agent 查询系统已有哪些角色 | `lark-cli apps +role-list --app-id "$app_id"` |
|
|
43
|
+
| Agent 创建/更新角色 | `lark-cli apps +role-create --app-id "$app_id" --name "<名称>"` / `+role-update --app-id "$app_id" --role-id <role_id>` |
|
|
44
|
+
| Agent 删除角色(高风险) | `lark-cli apps +role-delete --app-id "$app_id" --role-id <role_id> --yes`,执行前必须取得用户明确授权 |
|
|
45
|
+
| Agent 管理角色成员 | `lark-cli apps +role-member-list/add/remove --app-id "$app_id" --role-id <role_id>`(remove 为高风险,需授权) |
|
|
46
|
+
| 查询某用户命中哪些角色 | `lark-cli apps +role-match-list --app-id "$app_id" --user-id <ou_x>` |
|
|
47
|
+
| 创建 authz_permissions/authz_role_permissions 表 | `lark-cli apps +db-execute` 执行 DDL |
|
|
48
|
+
| 开发阶段新增/更新/删除权限点位 | `lark-cli apps +db-execute` 执行 INSERT/UPDATE/DELETE |
|
|
49
|
+
| 开发阶段初始化或调整角色-点位映射 | `lark-cli apps +db-execute` 执行 INSERT/DELETE |
|
|
50
|
+
| 运行态调整角色-点位映射(勾选/取消) | 由应用管理页面处理,**不属于** Agent 职责 |
|
|
51
|
+
| **应用前端**需要权限控制 | 使用 `<CanRole>` 或 `<Can>` 组件(参考 `authz-guide` skill) |
|
|
52
|
+
| **应用后端**需要权限控制 | 使用 `@CanRole` 或 `@Can` 装饰器(参考 `authz-guide` skill) |
|
|
53
|
+
|
|
54
|
+
> **禁止**在生成的应用代码(前端/后端)中调用 `lark-cli`。CLI 命令只在 Agent 对话终端中执行。
|
|
55
|
+
|
|
56
|
+
> 默认输出 JSON envelope,角色数据位于 `data.items` / `data.role` / `data.roles`。
|
|
57
|
+
|
|
58
|
+
## Action 决策流程
|
|
59
|
+
|
|
60
|
+
### Action 类型与触发场景
|
|
61
|
+
|
|
62
|
+
| Action | 触发场景 | 对应操作 |
|
|
63
|
+
| ------ | -------- |---------|
|
|
64
|
+
| QUERY | 需要了解当前系统已有哪些角色 | `lark-cli apps +role-list --app-id "$app_id"` |
|
|
65
|
+
| CREATE | 查询后发现所需角色不存在,需按设计方案批量创建 | `lark-cli apps +role-create --app-id "$app_id" --name "..." --description "..."` |
|
|
66
|
+
| UPDATE | 需要修改已有角色的名称或描述 | `lark-cli apps +role-update --app-id "$app_id" --role-id "..." --name "..."` |
|
|
67
|
+
| DELETE | 需要删除角色(高风险,不可逆) | 先 `+role-get` + `+role-member-list` 确认影响,取得授权后 `+role-delete --yes` |
|
|
68
|
+
| MEMBER | 需要查询/调整角色的用户、部门、群成员 | `+role-member-list/add/remove`(remove 高风险,需授权) |
|
|
69
|
+
| MATCH | 需要查询某用户命中哪些角色 | `lark-cli apps +role-match-list --app-id "$app_id" --user-id "<ou_x>"` |
|
|
70
|
+
| PERM_CREATE_TABLE | 首次启用动态权限:创建 authz_permissions/authz_role_permissions 表 | `lark-cli apps +db-execute` 执行 DDL |
|
|
71
|
+
| PERM_SEED | 初始化权限点位和角色-点位映射数据 | `lark-cli apps +db-execute` 执行 INSERT |
|
|
72
|
+
| PERM_ADD | 新增权限点位(新功能上线时) | `lark-cli apps +db-execute` 执行 INSERT + 同步更新 `@Can`/`<Can>` 代码 |
|
|
73
|
+
| PERM_UPDATE | 修改权限点位的 action/subject/description | `lark-cli apps +db-execute` 执行 UPDATE + 同步更新 `@Can`/`<Can>` 代码 |
|
|
74
|
+
| PERM_DELETE | 删除权限点位(功能下线时) | `lark-cli apps +db-execute` 执行 DELETE(级联删除映射)+ 移除 `@Can`/`<Can>` 代码 |
|
|
75
|
+
|
|
76
|
+
### 决策流程图
|
|
77
|
+
|
|
78
|
+
```text
|
|
79
|
+
权限设计方案
|
|
80
|
+
│
|
|
81
|
+
├─ 推荐模式:静态角色鉴权
|
|
82
|
+
│ └─ 新建 ──→ 按角色清单逐个 CREATE ──→ 编写 CanRole 代码(authz-guide)
|
|
83
|
+
│
|
|
84
|
+
├─ 推荐模式:动态权限点位鉴权
|
|
85
|
+
│ ├─ 新建 ──→ CREATE 角色 → PERM_CREATE_TABLE → PERM_SEED → 编写 @Can 代码(authz-guide)
|
|
86
|
+
│ └─ 升级(仅限历史 CanRole 代码迁移)──→ PERM_CREATE_TABLE → PERM_SEED → CanRole 升级为 Can(authz-guide)
|
|
87
|
+
│
|
|
88
|
+
├─ "给某功能加权限控制" / "新建某个角色"
|
|
89
|
+
│ └──→ QUERY(查询角色)
|
|
90
|
+
│ ├─ 角色存在 ──→ 编写鉴权代码(authz-guide)
|
|
91
|
+
│ └─ 角色不存在 ──→ CREATE ──→ 编写鉴权代码
|
|
92
|
+
│
|
|
93
|
+
├─ "新功能上线,需要新增权限点位" ──→ PERM_ADD + 同步 @Can/<Can> 代码
|
|
94
|
+
│
|
|
95
|
+
├─ "功能下线,删除权限点位" ──→ PERM_DELETE + 移除 @Can/<Can> 代码
|
|
96
|
+
│
|
|
97
|
+
├─ "修改角色信息" ──→ UPDATE
|
|
98
|
+
│
|
|
99
|
+
└─ "查某用户有哪些角色" ──→ MATCH
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 关键约束
|
|
103
|
+
|
|
104
|
+
**角色设计由权限设计方案承载**,本 skill 负责角色 CLI 操作和权限点位管理。
|
|
105
|
+
|
|
106
|
+
**日常权限开发流程**:QUERY → 判断是否 CREATE → 编写鉴权代码(参考 `authz-guide`)。
|
|
107
|
+
|
|
108
|
+
**动态权限点位初始化流程**:CREATE 角色 → PERM_CREATE_TABLE → PERM_SEED → 编写鉴权代码。
|
|
109
|
+
|
|
110
|
+
**权限点位变更**:PERM_ADD / PERM_UPDATE / PERM_DELETE **必须同步更新** `@Can`/`<Can>` 代码,确保数据库点位定义与代码中的鉴权声明一致。
|
|
111
|
+
|
|
112
|
+
**角色标识**:角色名称不是 role_id。只有名称时先用 `+role-list --name '<exact_name>'` 精确解析;多条命中让用户消歧,唯一命中后才使用返回的真实 role_id。
|
|
113
|
+
|
|
114
|
+
**mock 能力差异**:authz-cli 的 `role mock`(为用户配置模拟角色集)在 lark-cli 通道无对应命令,已移除;只读查询用户命中的角色用 MATCH(`+role-match-list`)。
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## 角色管理(`lark-cli apps +role-*`)
|
|
119
|
+
|
|
120
|
+
完整命令约定见 [references/role.md](references/role.md)。高频用法:
|
|
121
|
+
|
|
122
|
+
### 查询角色
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
# 分页列出全部角色
|
|
126
|
+
lark-cli apps +role-list --app-id "$app_id" --page-size 100
|
|
127
|
+
|
|
128
|
+
# 按精确名称解析 role_id
|
|
129
|
+
lark-cli apps +role-list --app-id "$app_id" --name '管理员'
|
|
130
|
+
|
|
131
|
+
# 读取角色详情
|
|
132
|
+
lark-cli apps +role-get --app-id "$app_id" --role-id <role_id>
|
|
133
|
+
|
|
134
|
+
# 查询某用户命中的角色(user-id 只接受 ou_...)
|
|
135
|
+
lark-cli apps +role-match-list --app-id "$app_id" --user-id <ou_x>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 创建角色
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
lark-cli apps +role-create --app-id "$app_id" \
|
|
142
|
+
--name "管理员" \
|
|
143
|
+
--description "拥有全部管理权限" \
|
|
144
|
+
--role-id "admin"
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**参数:**
|
|
148
|
+
|
|
149
|
+
- `--name`(必需):角色名称
|
|
150
|
+
- `--description`(可选):角色描述
|
|
151
|
+
- `--role-id`(可选):角色 ID。仅在需要稳定业务标识(如 `admin`,供权限点位表 `role_key` 引用)时传入,创建后不能修改;不传由平台分配
|
|
152
|
+
|
|
153
|
+
### 按设计方案批量创建
|
|
154
|
+
|
|
155
|
+
当权限设计方案已输出角色清单(含 name、roleId、description)时,按清单顺序逐个创建:
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# 按角色清单顺序执行,每个角色一条命令
|
|
159
|
+
lark-cli apps +role-create --app-id "$app_id" --name "读者" --role-id "reader" --description "浏览图书与分类,发起借阅"
|
|
160
|
+
lark-cli apps +role-create --app-id "$app_id" --name "图书编辑" --role-id "editor" --description "负责图书内容的创建与维护"
|
|
161
|
+
lark-cli apps +role-create --app-id "$app_id" --name "管理员" --role-id "admin" --description "拥有所有业务管理权限"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
> 创建完所有角色后,按权限设计方案的功能权限映射表编写鉴权代码(参考 `authz-guide`)。
|
|
165
|
+
|
|
166
|
+
### 更新角色
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
# 只传需要变更的字段(--name 或 --description)
|
|
170
|
+
lark-cli apps +role-update --app-id "$app_id" --role-id "admin" --name "管理员(全局)"
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### 删除角色(高风险)
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# 先确认影响范围,取得用户明确授权后再带 --yes 执行
|
|
177
|
+
lark-cli apps +role-get --app-id "$app_id" --role-id <role_id>
|
|
178
|
+
lark-cli apps +role-member-list --app-id "$app_id" --role-id <role_id>
|
|
179
|
+
lark-cli apps +role-delete --app-id "$app_id" --role-id <role_id> --yes
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### 角色成员管理
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
# 查询角色的用户、部门、群成员
|
|
186
|
+
lark-cli apps +role-member-list --app-id "$app_id" --role-id <role_id>
|
|
187
|
+
|
|
188
|
+
# 添加成员(open ID:用户 ou_...、部门 od-...、群 oc_...)
|
|
189
|
+
lark-cli apps +role-member-add --app-id "$app_id" --role-id <role_id> \
|
|
190
|
+
--users ou_x,ou_y --departments od-x --chats oc_x
|
|
191
|
+
|
|
192
|
+
# 定向移除成员(高风险,需授权)
|
|
193
|
+
lark-cli apps +role-member-remove --app-id "$app_id" --role-id <role_id> --users ou_x --yes
|
|
194
|
+
|
|
195
|
+
# 清空成员(不删除角色;高风险,需授权)
|
|
196
|
+
lark-cli apps +role-member-remove --app-id "$app_id" --role-id <role_id> --all --yes
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
> **成员参数只接受飞书 open ID**:`--users` 收 `ou_`、`--departments` 收 `od-`、`--chats` 收 `oc_`。妙搭的数字 user_id(例如数据库 `user_profile` 列用的那组测试用户)**不能用**,CLI 会直接拒绝并提示 `--users must use ou_ IDs`。
|
|
200
|
+
> 沙箱内取 open ID 只有两条路:`lark-cli contact +search-user --query "<姓名或邮箱>"`(要求唯一精确命中)、`lark-cli contact +get-user`(当前登录用户自己)。**两条都拿不到就停下向用户要 open ID——禁止用数字 ID 兜底,禁止编造。**
|
|
201
|
+
|
|
202
|
+
## 权限点位管理(`lark-cli apps +db-execute`)
|
|
203
|
+
|
|
204
|
+
> **SQL 执行通道**:所有 DDL/DML 只用 `lark-cli apps +db-execute --app-id "$app_id" --sql "<query>" --yes` 执行,不要调用其它 SQL 工具。建表规范(审计列、RLS、默认 policy、`IF NOT EXISTS`)、DML 规则与高风险授权要求**参阅 `lark-apps-db` skill**([../lark-apps-db/SKILL.md](../lark-apps-db/SKILL.md))。
|
|
205
|
+
|
|
206
|
+
> **职责边界**:
|
|
207
|
+
> - **开发阶段(Agent)**:通过 `+db-execute` 对 `authz_permissions`(点位定义)和 `authz_role_permissions`(角色-点位映射)两张表做 CURD,含建表、预填、点位增删改、初始映射调整。
|
|
208
|
+
> - **运行态(管理页面)**:只提供受限能力——角色-点位映射的勾选/取消。**禁止**管理页面提供权限点位本身的新增/删除功能(点位增删属于代码变更范畴,必须回到开发阶段走 `+db-execute` + 同步 `@Can`/`<Can>`)。
|
|
209
|
+
|
|
210
|
+
> **⚠️ 双表原则**:权限点位涉及 `authz_permissions`(点位定义)和 `authz_role_permissions`(角色-点位映射)两张表,初始化和变更时**必须同时处理两张表**,禁止只操作其中一张。
|
|
211
|
+
|
|
212
|
+
### PERM_CREATE_TABLE — 建表
|
|
213
|
+
|
|
214
|
+
首次启用动态权限点位时执行。两张表的完整建表 DDL、RLS/policy 补齐要求、`role_key` ↔ 角色 ID 的对应关系见 [references/permission-points.md](references/permission-points.md)。
|
|
215
|
+
|
|
216
|
+
### PERM_SEED — 预填初始数据
|
|
217
|
+
|
|
218
|
+
按权限设计方案的「权限点位定义」和「角色-点位初始映射」表预填:
|
|
219
|
+
|
|
220
|
+
```sql
|
|
221
|
+
-- 按「权限点位定义」表
|
|
222
|
+
INSERT INTO authz_permissions (action, subject, description) VALUES
|
|
223
|
+
('read', 'Task', '查看任务'),
|
|
224
|
+
('create', 'Task', '创建任务'),
|
|
225
|
+
('update', 'Task', '编辑任务'),
|
|
226
|
+
('delete', 'Task', '删除任务');
|
|
227
|
+
|
|
228
|
+
-- 按「角色-点位初始映射」表
|
|
229
|
+
INSERT INTO authz_role_permissions (role_key, permission_id) VALUES
|
|
230
|
+
('admin', (SELECT id FROM authz_permissions WHERE action='read' AND subject='Task')),
|
|
231
|
+
('admin', (SELECT id FROM authz_permissions WHERE action='create' AND subject='Task')),
|
|
232
|
+
('member', (SELECT id FROM authz_permissions WHERE action='read' AND subject='Task'));
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
> 以上 SQL 仅为示例,实际数据根据权限设计方案生成。
|
|
236
|
+
|
|
237
|
+
### PERM_ADD — 新增权限点位
|
|
238
|
+
|
|
239
|
+
新功能上线时,新增点位 + 初始映射 + 同步鉴权代码:
|
|
240
|
+
|
|
241
|
+
```sql
|
|
242
|
+
-- 1. 新增点位定义(authz_permissions 表)
|
|
243
|
+
INSERT INTO authz_permissions (action, subject, description) VALUES
|
|
244
|
+
('export', 'Task', '导出任务');
|
|
245
|
+
|
|
246
|
+
-- 2. 为需要该权限的角色添加映射(authz_role_permissions 表)
|
|
247
|
+
INSERT INTO authz_role_permissions (role_key, permission_id) VALUES
|
|
248
|
+
('admin', (SELECT id FROM authz_permissions WHERE action='export' AND subject='Task'));
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
> **必须同步**:
|
|
252
|
+
> - 在后端对应的 Controller 方法上添加 `@Can('export', 'Task')`,前端添加 `<Can action="export" subject="Task">`
|
|
253
|
+
> - **禁止**只插入 authz_permissions 而不处理 authz_role_permissions,否则新点位无任何角色拥有
|
|
254
|
+
|
|
255
|
+
### PERM_UPDATE — 修改权限点位
|
|
256
|
+
|
|
257
|
+
修改已有点位的 action、subject 或 description:
|
|
258
|
+
|
|
259
|
+
```sql
|
|
260
|
+
-- 修改 authz_permissions 表(authz_role_permissions 通过外键 permission_id 关联,无需修改)
|
|
261
|
+
UPDATE authz_permissions SET description = '导出任务列表为 Excel' WHERE action = 'export' AND subject = 'Task';
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
> 如果修改了 action 或 subject,**必须同步更新**所有引用该点位的 `@Can`/`<Can>` 代码。authz_role_permissions 通过 `permission_id` 外键关联,不受 action/subject 变更影响。
|
|
265
|
+
|
|
266
|
+
### PERM_DELETE — 删除权限点位
|
|
267
|
+
|
|
268
|
+
功能下线时,删除点位 + 自动级联删除映射 + 移除鉴权代码:
|
|
269
|
+
|
|
270
|
+
```sql
|
|
271
|
+
-- 删除 authz_permissions 记录,authz_role_permissions 中关联的映射会被 ON DELETE CASCADE 自动删除
|
|
272
|
+
DELETE FROM authz_permissions WHERE action = 'export' AND subject = 'Task';
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
> **必须同步**:移除后端的 `@Can('export', 'Task')` 装饰器和前端的 `<Can action="export" subject="Task">` 组件。
|
|
276
|
+
> 虽然 authz_role_permissions 会自动级联删除,仍需**确认**不存在其他代码依赖被删除的点位。
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## Common Mistakes
|
|
281
|
+
|
|
282
|
+
| 错误 | 正确做法 |
|
|
283
|
+
| ---- | -------- |
|
|
284
|
+
| 在应用代码中调用 `lark-cli` | CLI 仅供 Agent 终端执行;应用代码用 CanRole 组件/装饰器(参考 `authz-guide`) |
|
|
285
|
+
| 用角色名称当 role_id 直接更新/删除 | 先 `+role-list --name '<exact_name>'` 精确解析出 role_id,多条命中让用户消歧 |
|
|
286
|
+
| 未授权就执行 `+role-delete --yes` / `+role-member-remove --all --yes` | 删除类操作高风险不可逆,先展示影响范围取得明确授权;exit-10 按沙箱约定处理,绝不静默补 `--yes` |
|
|
287
|
+
| 只创建角色不编写鉴权代码 | 创建角色后必须编写鉴权代码(参考 `authz-guide`) |
|
|
288
|
+
| 没有设计方案就大批量创建角色 | 先确认是否有权限设计方案输出的角色清单,再按清单逐个 CREATE |
|
|
289
|
+
| 动态权限点位场景只创建角色不建表预填 | 需要执行 PERM_CREATE_TABLE + PERM_SEED |
|
|
290
|
+
| 在管理页面提供权限点位的增删改 | 权限点位的增删改由 Agent 通过 PERM_ADD/UPDATE/DELETE 操作,管理页面只做角色-点位映射 |
|
|
291
|
+
| 新增/修改/删除权限点位后不同步代码 | PERM_ADD/UPDATE/DELETE 后**必须同步**更新对应的 `@Can`/`<Can>` 代码 |
|
|
292
|
+
| PERM_ADD 只插入 authz_permissions 不插入 authz_role_permissions | 新增点位后必须同时为相关角色添加映射,否则无角色拥有该权限 |
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# 权限点位表建表 DDL(PERM_CREATE_TABLE)
|
|
2
|
+
|
|
3
|
+
首次启用动态权限点位时执行。通过 `lark-cli apps +db-execute --app-id "$app_id" --sql "<ddl>" --yes` 下发;
|
|
4
|
+
SQL 执行通道、建表规范与高风险授权要求以 `lark-apps-db` skill 为准。
|
|
5
|
+
|
|
6
|
+
## 两张表
|
|
7
|
+
|
|
8
|
+
```sql
|
|
9
|
+
CREATE TABLE IF NOT EXISTS authz_permissions (
|
|
10
|
+
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
|
11
|
+
action VARCHAR(100) NOT NULL,
|
|
12
|
+
subject VARCHAR(100) NOT NULL,
|
|
13
|
+
description TEXT DEFAULT '',
|
|
14
|
+
creator user_profile NOT NULL,
|
|
15
|
+
_created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
16
|
+
_created_by user_profile,
|
|
17
|
+
_updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
18
|
+
_updated_by user_profile,
|
|
19
|
+
UNIQUE(action, subject)
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
CREATE TABLE IF NOT EXISTS authz_role_permissions (
|
|
23
|
+
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
|
24
|
+
role_key VARCHAR(100) NOT NULL,
|
|
25
|
+
permission_id UUID NOT NULL REFERENCES authz_permissions(id) ON DELETE CASCADE,
|
|
26
|
+
creator user_profile NOT NULL,
|
|
27
|
+
_created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
28
|
+
_created_by user_profile,
|
|
29
|
+
_updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
30
|
+
_updated_by user_profile,
|
|
31
|
+
UNIQUE(role_key, permission_id)
|
|
32
|
+
);
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 两条必读约束
|
|
36
|
+
|
|
37
|
+
> **RLS 与默认 policy**:以上仅为业务列示意,实际建表必须按 `lark-apps-db` skill 的 CREATE TABLE Template 在**同一次 `+db-execute` 调用**中补齐 `ENABLE ROW LEVEL SECURITY` 和 4 条默认 policy(两张表都要),并在执行前取得用户授权。
|
|
38
|
+
|
|
39
|
+
> **`role_key` ↔ 角色 ID**:`authz_role_permissions.role_key` 存储的值必须等于角色的 role_id(`+role-create --role-id` 传入的值,或平台分配后从 `+role-list` 读到的值)。两者是同一个标识,INSERT 映射时 `role_key` 填 `'admin'`、`'editor'` 等角色 ID,运行时鉴权也用它匹配用户拥有的角色。
|