由 AdminResource 生成的管理后台:列表、表单、操作、仪表盘、RBAC、CSRF 防护和审计日志
代码12 个文件上下文约 849 个 token扫描通过
安装
$
genpm add @core/admin你将获得
- 源代码位于 src/lib/admin/,共 12 个文件。 (56.9 kB)
- AI 规则位于 src/lib/admin/AGENTS.md,另附 IDE 规则文件。
- 自动为你解析 @core/auth, @core/contracts, @core/db, @core/rbac, @core/ui。
README
此包没有 README。
约 849 个 token→ src/lib/admin/AGENTS.md→ .cursor/rules/genpm-core-admin.mdc
这正是你的 AI 在 src/lib/admin 中工作时读取的内容。不会向其上下文添加其他任何内容。
@core/admin — rules for AI agents
Purpose
Admin panel generated from AdminResource descriptions (from @core/contracts): navigation, dashboard widgets,
searchable/sortable lists, create/edit forms, record actions with confirmation, and delete. No per-resource screens:
any module that exports an AdminResource appears in the panel. Server side: session from @core/auth, permissions
from @core/rbac (admin:access + <resource>:<action>), CSRF protection on writes and an audit log of every change.
Table: admin_audit.
Map
index.ts— server API:defineAdmin,handleAdminApi,adminContextFor,listAudit,auditAdminResource,countWidget,listWidget,fieldsFromZod.client.ts—'use client':AdminApp,createAdminApi,FieldControl,defaultLabels, renderer types.admin.css— layout on @core/ui tokens.constants.ts—ADMIN_HEADER(shared by server and client).adapters/hono.ts—adminRoutes(admin).adapters/next.ts—adminRouteHandlers(admin).
Integration
- Install @core/auth, @core/rbac and @core/ui first; run migrations as in
src/lib/db/AGENTS.md(admin_audit). - Create
src/genpm/admin.ts:
Every installed module'simport { defineAdmin, auditAdminResource } from '@/lib/admin'; import { mediaAdminResource } from '@/lib/media'; export const admin = defineAdmin({ title: 'My site', resources: [mediaAdminResource, auditAdminResource], widgets: [] });AGENTS.mdsays which resources to add here. - API route. Next:
app/api/admin/[...path]/route.ts→export const { GET, POST, PUT, DELETE } = adminRouteHandlers(admin); export const dynamic = 'force-dynamic';Hono:app.route('/api/admin', adminRoutes(admin)). - Page. Next:
app/admin/[[...path]]/page.tsxrenders a client component that imports../lib/ui/ui.css,../lib/admin/admin.cssand returns<AdminApp basePath="/admin" path={(await params).path?.join('/') ?? ''} />. Protect the page itself too (redirect to sign-in when there is no session) and addrobots: { index: false }. - Rich text, media pickers or blocks: pass
renderers={{ richText: MyEditorField, media: MyMediaPicker }}. Without them those fields fall back to a JSON textarea / relation select. - Translate the UI with
labels={{ save: t('admin.save'), … }}(keys:defaultLabels). - Verify: a user without
admin:accessgets 403 on/api/admin/schema; an editor sees only their resources; an edit creates a row inadmin_auditwith before/after.
Conventions
- Resources enforce permissions themselves (
ctx.can(...)); the panel hides what the user cannot do but the server never trusts that. Use<resource>:<action>:ownfor author-only rules. - Field names may be nested (
data.title); read-only fields are shown but never sent. - Money fields hold integer minor units (or
{ amount, currency }); the form edits decimals. - Actions that change state declare
available(row)so the panel only offers them when valid.
Don't
- Don't call the admin API from other origins or without the
x-admin-request: 1header (requests are rejected). - Don't write per-resource admin pages; extend the
AdminResourceor add a field renderer instead. - Don't put secrets or full payment data in resource rows: the audit log stores before/after snapshots.
- Don't expose
/adminin the sitemap or let it be indexed.
# @core/admin — rules for AI agents
## Purpose
Admin panel generated from `AdminResource` descriptions (from @core/contracts): navigation, dashboard widgets,
searchable/sortable lists, create/edit forms, record actions with confirmation, and delete. No per-resource screens:
any module that exports an `AdminResource` appears in the panel. Server side: session from @core/auth, permissions
from @core/rbac (`admin:access` + `<resource>:<action>`), CSRF protection on writes and an audit log of every change.
Table: `admin_audit`.
## Map
- `index.ts` — server API: `defineAdmin`, `handleAdminApi`, `adminContextFor`, `listAudit`, `auditAdminResource`, `countWidget`, `listWidget`, `fieldsFromZod`.
- `client.ts` — `'use client'`: `AdminApp`, `createAdminApi`, `FieldControl`, `defaultLabels`, renderer types.
- `admin.css` — layout on @core/ui tokens. `constants.ts` — `ADMIN_HEADER` (shared by server and client).
- `adapters/hono.ts` — `adminRoutes(admin)`. `adapters/next.ts` — `adminRouteHandlers(admin)`.
## Integration
1. Install @core/auth, @core/rbac and @core/ui first; run migrations as in `src/lib/db/AGENTS.md` (`admin_audit`).
2. Create `src/genpm/admin.ts`:
```ts
import { defineAdmin, auditAdminResource } from '@/lib/admin';
import { mediaAdminResource } from '@/lib/media';
export const admin = defineAdmin({ title: 'My site', resources: [mediaAdminResource, auditAdminResource], widgets: [] });
```
Every installed module's `AGENTS.md` says which resources to add here.
3. API route. Next: `app/api/admin/[...path]/route.ts` →
`export const { GET, POST, PUT, DELETE } = adminRouteHandlers(admin); export const dynamic = 'force-dynamic';`
Hono: `app.route('/api/admin', adminRoutes(admin))`.
4. Page. Next: `app/admin/[[...path]]/page.tsx` renders a client component that imports `../lib/ui/ui.css`,
`../lib/admin/admin.css` and returns `<AdminApp basePath="/admin" path={(await params).path?.join('/') ?? ''} />`.
Protect the page itself too (redirect to sign-in when there is no session) and add `robots: { index: false }`.
5. Rich text, media pickers or blocks: pass `renderers={{ richText: MyEditorField, media: MyMediaPicker }}`.
Without them those fields fall back to a JSON textarea / relation select.
6. Translate the UI with `labels={{ save: t('admin.save'), … }}` (keys: `defaultLabels`).
7. Verify: a user without `admin:access` gets 403 on `/api/admin/schema`; an editor sees only their resources; an edit
creates a row in `admin_audit` with before/after.
## Conventions
- Resources enforce permissions themselves (`ctx.can(...)`); the panel hides what the user cannot do but the server
never trusts that. Use `<resource>:<action>:own` for author-only rules.
- Field names may be nested (`data.title`); read-only fields are shown but never sent.
- Money fields hold integer minor units (or `{ amount, currency }`); the form edits decimals.
- Actions that change state declare `available(row)` so the panel only offers them when valid.
## Don't
- Don't call the admin API from other origins or without the `x-admin-request: 1` header (requests are rejected).
- Don't write per-resource admin pages; extend the `AdminResource` or add a field renderer instead.
- Don't put secrets or full payment data in resource rows: the audit log stores before/after snapshots.
- Don't expose `/admin` in the sitemap or let it be indexed.
应用 .genpmignore 后将被注入的确切目录树。固定于
// Tablas de @core/admin. Las recoge drizzle-kit vía src/lib/db/drizzle.config.ts.
import { index, jsonb, pgTable, text, timestamp } from 'drizzle-orm/pg-core';
import { primaryId } from '../db/index.ts';
/** Quién cambió qué y cuándo en el panel (crear, editar, borrar, acciones). */
export const adminAudit = pgTable(
'admin_audit',
{
id: primaryId('aud'),
userId: text('user_id').notNull(),
resource: text('resource').notNull(),
recordId: text('record_id'),
action: text('action').notNull(),
/** Antes/después (recortado) para crear, editar y acciones. */
diff: jsonb('diff').$type<{ before?: unknown; after?: unknown; input?: unknown }>().notNull().default({}),
createdAt: timestamp('created_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),
},
(t) => [index('admin_audit_record_idx').on(t.resource, t.recordId, t.createdAt), index('admin_audit_user_idx').on(t.userId, t.createdAt)],
);
export type AdminAudit = typeof adminAudit.$inferSelect;
此包未声明 MCP 服务器。
| 版本 | 提交 | 发布时间 | 扫描 |
|---|---|---|---|
| 1.0.0 | 3b5bae0 | 4小时前 | 扫描通过 |
- 建议
- GenPM 会给出 npm 命令建议,只有你同意时才会运行。
- 扫描
- 扫描通过 · 0 个问题
- 提交
- v1.0.0 → 3b5bae0f3259afef9e31e783556de2dbcff25234 · 获取后已校验
- 脚本
- 无。GenPM 从不运行包中的代码。
- 许可证
- MIT
- 质量
- 100/100
- 可识别的许可证已满足
- AGENTS.md 说明了用途已满足
- AGENTS.md 包含集成步骤已满足
- AGENTS.md 列出约定或禁止事项已满足
- 包含测试已满足
- 通过安全扫描已满足
- 最近 6 个月内发布已满足
- 已验证的发布者已满足
- 摘要和关键词已满足
- 举报
- 发现问题了吗?