# Supabase Facade AI 快速开发指南

## 更新记录

- 2026-07-16: 建立 Go、React 和 Facade 三方契约同步流程。
- 2026-07-16: 根据 Base44 访问申请实现补齐规则、模块地图、复用决策、测试矩阵和收尾清单。

## 1. 使用目的

本文用于让后续 AI 在不破坏安全边界、公共 API 和发布流程的前提下，快速扩展 `node_facade_base44_supabase`。

项目类型固定为 `node_facade_xx` 应用组合封装库：

- 不启动独立 Web 服务；
- 不接管 Base44 Function 或主程序生命周期；
- 对页面暴露稳定场景 API；
- 组合 `node_lib_base44_core`，但不把 Go/Supabase 领域逻辑下沉到 core；
- 不直连 Supabase。

## 2. AI 必读顺序

开始改动前必须依次阅读：

1. `C:\Application\qoder\node\.qoder\rules\rules_node.md`；
2. `rules_node_library.md` 和 `rules_text_i18n.md`；
3. 本项目 `README.md`、`docs/project-status.md`、`docs/usage.md`；
4. 本文和目标模块对应的 `docs/api/supabase.md`；
5. `node_lib_base44_core/docs/fun/ai_facade_development.md`；
6. Go 的真实路由、Handler、Body allowlist 和错误映射；
7. React/Base44 页面实际调用和类型；
8. 目标功能的冻结需求或交接文档。

禁止仅根据接口名称、旧文档或聊天摘要猜测路径、字段、鉴权和响应。

## 3. 权威事实优先级

```text
Go 路由和 Handler       服务端实际路径、方法、Body/Query allowlist、HTTP 错误
数据库冻结 RPC 契约     事务、幂等、审计、并发和数据不变量
Facade 源码与测试       页面 API、PascalCase 到 wire 字段映射、代理安全
React/Base44 页面       调用时机、状态展示和客户端类型
需求文档                产品流程和尚未实现项
```

如果这些来源不一致：

1. 不在 Facade 中偷偷增加猜测兼容；
2. 先记录差异；
3. 以实际 Go 路由作为当前网络事实；
4. 需要改变冻结契约时先让维护者确认。

## 4. 当前数据流

```text
Base44 Web
  │  场景 API、Go AccessToken 元数据、IdempotencyKey 元数据
  ▼
CreateSupabaseClient
  ▼
Base44 Backend Function
  │  node_lib_base44_core.ResolveBase44User
  │  Base44 固定路径由 Facade 签发 RS256 assertion 并重建 Body
  ▼
CreateSupabaseFunctionHandler
  │  精确路径、Bearer、幂等 Header、错误白名单
  ▼
go_qoder_file /ts/dbbase/*
  │  Session、Staff Context、Permission、幂等、限流、固定 RPC
  ▼
Supabase V3
```

Supabase Secret、`service_role` Key、数据库连接串、Go HMAC pepper 和 replay pepper 都不得进入本项目或页面。

## 5. 源码模块地图

| 模块 | 单一职责 | 修改前必须核对 |
| --- | --- | --- |
| `index.js` | 唯一公共导出入口 | 是否真的需要新增根导出 |
| `supabase_client.js` | 组合 Client Context 和四类 Service | 不重复实现 core 客户端装配 |
| `supabase_proxy.js` | Go 路径白名单和安全错误附加字段 | 不加入任意 URL/RPC |
| `supabase_function_handler.js` | 顶层元数据、Header 和 Base44 固定请求编排 | Go Bearer 与 Base44 assertion 边界 |
| `service_paths.js` | 所有固定路径、公开 Auth 和幂等判断 | Go `main.go` 路由 |
| `facade_request.js` | 页面 Payload、Go Token 和领域 envelope | Token 不进入 Body |
| `facade_error.js` | 页面可消费的结构化错误 | 只保留允许公开字段 |
| `base44_assertion.js` | 可信身份归一化和 RS256 assertion | Go verifier 和 Function Secret |
| `base44_request.js` | Base44 请求说明、保护字段和最终 Body | Go Body allowlist |
| `auth_service.js` | 登录、会话、Base44、邀请、注册和重置场景 API | Auth 路由和公开性 |
| `crud_service.js` | 受控 CRUD wire 映射 | Go CRUD 白名单 |
| `platform_service.js` | 平台 App 场景 | 平台权限和幂等 |
| `admin_service.js` | App 内用户、Staff、Role、Permission、审计 | App 边界和权限码 |
| `idempotency_key.js` | 幂等键生成和读取 | 哪些写操作真实支持幂等 |
| `paging.js` | cursor 分页聚合 | 最大页数和返回字段 |
| `messages.js` | 固定错误文案 | 不在业务逻辑散落文案 |

内部模块不得被业务项目深层引用。公共入口仍是：

```js
const NodeFacadeBase44Supabase = require('node_facade_base44_supabase');
```

## 6. 公共复用归属决策

### 6.1 应下沉 `node_lib_base44_core`

同时满足以下条件才下沉：

- 与 Go、Supabase、Wix、ThinkSign 等后台名称无关；
- 不依赖具体业务路径、字段、错误码和权限；
- 两个以上 facade 会以相同语义复用；
- 可以通过稳定参数配置；
- 不要求 core 读取业务环境变量。

当前已经下沉：

- Base44 `auth.me()` 用户解析：`ResolveBase44User`；
- 固定上游代理、路径白名单、超时和文件转发；
- Facade Client Context 装配；
- 代理层结构化错误。

### 6.2 必须留在本 Facade

- `/ts/dbbase/*` 路径和 Go wire 字段；
- Base44 assertion Claims、issuer/audience/App 组合；
- 访问申请说明、保护字段和幂等规则；
- Go `ret_str` 解包和领域错误；
- Supabase CRUD、平台和权限管理场景。

### 6.3 应留在 Base44 页面

- 页面加载、按钮状态和用户交互；
- 同一次逻辑提交保存并复用幂等键；
- 访问状态对应的展示文案和导航；
- Go Session Token 的现有客户端会话存储。

不要为了减少几行代码把业务条件塞入 core，也不要把可信身份、assertion 或内部 App 映射下放到页面。

## 7. 新接口标准流程

### 7.1 先确认契约

1. 在 Go `main.go` 确认路径和方法已经注册。
2. 阅读对应 Handler 的 Body/Query allowlist。
3. 确认使用 Base44 assertion、Go Bearer Token，还是不需要认证。
4. 确认是否需要 `Idempotency-Key`。
5. 确认成功响应使用 `ret_str` 还是 CRUD 原始结构。
6. 确认非 2xx code、HTTP 状态和允许公开的恢复字段。

### 7.2 决定模块

```text
登录/会话/邀请/注册/重置/Base44  -> auth_service.js
通用受控表操作                    -> crud_service.js
平台级 App                        -> platform_service.js
App 内管理                        -> admin_service.js
路径/公开性/幂等                  -> service_paths.js
服务端可信 Body                   -> 专用领域模块，不能塞进页面 client
```

涉及权限、跨表事务、邮件、审计、注册、管理员动作或 Session 的操作必须走 Go 固定领域接口，不得为了少写路由而开放任意 RPC。

### 7.3 实现 PascalCase 到 wire 映射

页面 API 使用 PascalCase；Go 明确要求的 JSON 字段保持 wire 格式。例如：

```text
RequestMessage -> request_message
IdempotencyKey -> Idempotency-Key Header
AccessToken    -> Authorization: Bearer Header
```

服务端注入字段不得出现在页面 API 参数中。

### 7.4 测试优先补齐

每个新公开方法至少测试：

- 最终路径和 HTTP 方法；
- Body/Query 的精确字段；
- 是否带 Authorization；
- 是否带 Idempotency-Key；
- 成功 `ret_str`；
- 非 2xx `code/status/request_id`；
- 空值、类型、长度、路径编码和保护字段。

## 8. Base44 assertion 接口特殊规则

`access-status`、`access-requests`、`exchange` 必须遵循：

- Backend Function 强制取得当前 Base44 用户；
- 使用 core `ResolveBase44User`，不得复制 `auth.me()` 客户端校验；
- 每次调用签发新的 assertion 和 JTI；
- assertion 最长 60 秒，当前建议 45 秒；
- 页面不能提交 Subject、Email、Disabled、Provider App ID 或内部摘要；
- 只有旧 exchange 兼容输入允许出现 assertion，但服务端会忽略并重签；
- access-status 和创建申请若提交 assertion，必须拒绝；
- 三个最终 Go Body 由 `base44_request.js` 精确重建；
- 创建申请使用稳定幂等键，但重试必须使用新 assertion/JTI；
- 三个接口都不发送 Go Authorization。

修改 assertion 前必须同时核对：

- `base44_assertion.js`；
- Go `src/supabaseauth/base44.go`；
- `ACCESS_REQUEST_REQUIREMENTS.md`；
- `base44-access-request-node-facade-handoff.md`；
- assertion 和 Handler 安全测试。

## 9. 安全硬约束

- 不引入 `@supabase/supabase-js`。
- 不接收或暴露 Supabase Secret、`service_role`、数据库连接串。
- 不开放 `/ts/xdata`、任意 PostgREST、任意 RPC、任意外部 URL。
- 不把 AccessToken、IdempotencyKey、assertion 私钥或 JTI 放入业务 Body、URL 或日志。
- 公开 Auth 路径必须使用精确集合；其他 Auth 路径默认需要 Go Bearer。
- `app_id`、Actor、Staff、Permission、限流和内部摘要不能由浏览器覆盖。
- CRUD 不支持 hard delete。
- 完整上游错误对象、SQLSTATE、SQL 文本和堆栈不传页面。
- `RetryAllowedAt` 等附加错误字段必须逐字段白名单处理。
- RLS 即使启用也只是数据库第二道边界，不能替代 Go 领域鉴权。

## 10. 文档同步矩阵

| 变更 | 必须更新 |
| --- | --- |
| 新增/修改公共方法 | `docs/api/supabase.md`、测试 |
| 新增配置或 Secret | `docs/usage.md`、`docs/project-status.md` |
| 改变模块或组合流程 | `docs/fun/composition.md`、本文 |
| 重要功能、修复或复用提取 | `docs/logs/YYYY-MM-DD-*.md` |
| 当前能力、待办或验证变化 | `docs/project-status.md` |
| 新增重要文档 | `README.md` 索引 |
| 公共 core API | core 的 API、usage、status、logs 和受影响 facade |

README 只做入口索引，不复制完整 API 和实施方案。

## 11. 常见错误

- 在 Facade 再写一套 Base44 `auth.me()` 解析，而不复用 core。
- 同时在 `auth_service` 和 Handler 复制申请说明长度校验。
- 在多个文件硬编码同一 Base44 路径。
- 只修改 Service，忘记公开路径或幂等规则。
- 把浏览器 assertion、邮箱或 App ID 当作可信字段。
- 为通用 CRUD 增加 delete。
- 把 Go 非 2xx 统一改成 500/503。
- 示例缺少真实必填配置，导致复制后不能运行。
- 只更新聊天说明，不更新 `docs/`。
- 修改公开 API 后直接改版本、提交或发布，未等待维护者确认。

## 12. 本地验证顺序

先验证 core，再验证 Facade：

```bat
cd C:\Application\qoder\node\node_lib_base44_core
npm.cmd run check
npm.cmd test

cd C:\Application\qoder\node\node_facade_base44_supabase
npm.cmd run check
npm.cmd test
node examples/basic_usage.js
npm.cmd pack --dry-run --json
npm.cmd audit --omit=dev
```

PowerShell 禁止执行 `npm.ps1` 时使用 `npm.cmd`，不要修改系统 ExecutionPolicy。

真实联调还需覆盖：

- Base44 Function Secret 和官方 SDK 用户字段；
- 三个 Base44 用户端 Go 接口；
- application available、pending、approved exchange、disabled；
- JTI replay、幂等冲突、冷却和共享限流；
- 普通用户、App 管理员、平台管理员；
- 过期 Session、未选择 Staff、并发版本冲突。

## 13. 收尾审查清单

### 源码

- 没有 TODO、占位函数或深层依赖导入；
- 公共 API 只从 `index.js` 导出；
- PascalCase 变量/方法与 snake_case 文件名符合规则；
- 固定文案集中在 `messages.js`；
- 新文件已加入 `npm run check`；
- package 的 `files` 不包含 Secret、`.env`、真实 Token 或大文件。

### 复用

- 两个以上 facade 的相同通用能力已评估是否下沉 core；
- Go/Supabase 业务条件没有进入 core；
- 当前项目内部没有重复路径、Body 校验或错误映射。

### 文档

- API、usage、composition、status、logs 与源码一致；
- 示例包含全部必填配置且可执行；
- 已完成和待完成状态没有混写；
- 历史交接文档标明当前实施状态。

### 验证与发布

- core 与 Facade 本地检查、测试和 pack 通过；
- 未经确认不修改版本、不提交、不推送、不建 tag；
- 用户确认后先发布 core，再发布 Facade；
- Gitee 分支/tag 和依赖方固定 ref 验证完成后才算云端闭环。

## 14. 相关文档

- [公共 API](../api/supabase.md)
- [使用说明](../usage.md)
- [组合流程](composition.md)
- [Base44 访问申请实施交接](base44-access-request-node-facade-handoff.md)
- [项目状态](../project-status.md)
- [core AI Facade 开发指南](../../../node_lib_base44_core/docs/fun/ai_facade_development.md)
