# Workspace Readonly Access Contract Plan

## Current Design

- `GET /api/workspaces/{workspace_id}` 通过 `require_workspace_access()` 判定读权限。
- 目标契约是：workspace detail 直链对已登录用户可读；非 owner 默认只读。
- 只有 `workspaces.user_id` 指向的 canonical owner 可编辑。
- `shared` / `is_shared` 不再是产品概念；不作为权限、展示状态或 Lark workspace 特例。
- `transfer` 保留，只负责更新 canonical owner。

## Risks

- 把 `is_shared` 当成读权限门槛，会让未 shared 的手动 workspace 和 Lark workspace 直链错误返回 403。
- 继续保留 editor/member 写权限会和“只有 owner 才能 edit”冲突。
- 放开的是读取 detail/files/messages/sources 等 read API；写 API 仍必须走 owner-only 权限。
- 读路径不能做写入修复；不应为了 Lark 访问去 backfill `is_shared`。

## Target Contract

- 任意已登录用户打开存在的 workspace detail API 都返回 workspace row。
- `GET /api/workspaces` 只返回当前用户 own 的 workspace；别人 workspace 只通过 detail 直链读取。
- `can_edit=true` 只来自 `workspaces.user_id == current_user.id`。
- `require_workspace_editor()` 作为旧函数名保留，但语义改为 owner-only write access。
- Lark workspace 不需要特殊 shared/backfill 逻辑。
- 旧 DB 列/表可暂时保留作为历史存储，不再参与权限和 UI。

## Implementation Steps

1. 恢复 `require_workspace_access()` 的 detail 直链只读契约：workspace 存在即允许读；列表仍只返回自己的 workspace。
2. 将 `require_workspace_owner()` / `require_workspace_editor()` 都收敛到 canonical owner-only。
3. 移除 `/share` API、前端 Share/Shared UI、Lark `is_shared` 特判和 backfill 方向。
4. 增加本地契约测试：手动 workspace 和 Lark workspace 对其他用户都可 readonly 打开，但不能 edit；transfer 后新 owner 可 edit，旧 owner 只读。

## Verification Checklist

- 跑 Lark bot 相关测试，覆盖新建 `lark-ws-*` 的 readonly 访问。
- 跑 workspace 权限相关测试，确保未 shared 的手动 workspace outsider 也能 readonly 访问且不能 edit。
- 跑 frontend typecheck，确保 Share/Shared UI 和 API client 引用都移除。
- 线上验证需要 AWS SSO 可用后查 prod DB/API：目标 workspace 存在时，非 owner 调 `GET /api/workspaces/{id}` 返回 `can_edit=false`，不依赖 `is_shared`。
