Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 67 additions & 8 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@

```Markdown
# 标题1
## 标题2
## 标题2
```

每点击一行,左边都有加号按钮,可以快捷添加你要的内容块

![image.png](https://pub-fa1987abe8794da6ba45cdf9284954b3.r2.dev/users/7/contributing-guide/1765632611285-image.png)
Expand Down Expand Up @@ -71,7 +71,6 @@

点击右上角的commit changes


4. 点击 `Commit changes`,若是第一次投稿,GitHub 会提示先 Fork 仓库;按提示操作一次即可
![fork](./public//git_assets/need_fork.png)

Expand Down Expand Up @@ -182,31 +181,34 @@ git push origin doc_raven
**解决方案**:

1. **确保使用正确的 pnpm 版本**:

```bash
# 检查当前版本
pnpm --version

# 应该显示: 10.20.0
# 如果不是,请使用以下命令之一:

# 方法 1: 使用 corepack(推荐)
corepack enable
corepack prepare pnpm@10.20.0 --activate

# 方法 2: 全局安装
npm install -g pnpm@10.20.0
```

2. **验证版本一致性**:

```bash
pnpm check:pnpm-version
```

3. **如果 lockfile 已经被错误修改**:

```bash
# 丢弃 lockfile 的修改
git checkout pnpm-lock.yaml

# 确认使用正确的 pnpm 版本后重新安装
pnpm install
```
Expand All @@ -217,10 +219,12 @@ git push origin doc_raven
#### 问题:CI 检查失败,提示 lockfile 不一致

这通常意味着:

1. 你本地使用的 pnpm 版本与项目要求的不一致
2. lockfile 被错误修改或损坏

**解决方案**:

```bash
# 1. 确认并切换到正确的 pnpm 版本
corepack enable
Expand All @@ -239,12 +243,14 @@ git status
#### 问题:为什么要使用 corepack 而不是全局安装?

**Corepack 的优势**:

- 自动读取 `package.json` 的 `packageManager` 字段
- 每个项目可以使用不同的 pnpm 版本而不冲突
- 新贡献者克隆项目后自动使用正确的版本
- 减少版本不匹配导致的问题

**如何为团队启用 corepack**:

```bash
# 一次性设置,之后所有项目都会受益
corepack enable
Expand Down Expand Up @@ -305,13 +311,13 @@ pnpm check:pnpm-version
#### ⚠️ 为什么版本一致性很重要?

不同版本的 pnpm 在序列化 `pnpm-lock.yaml` 时可能使用不同的格式(如单引号 vs 双引号),导致:

- PR 中产生大量无意义的 diff
- 增加代码审查负担
- 可能导致 CI 检查失败

我们的 CI 工作流会自动检查版本一致性,如果检测到版本不匹配会导致构建失败。


### 3. 本地开发

运行开发服务器:
Expand Down Expand Up @@ -343,6 +349,59 @@ pnpm postinstall # 同步必要的 Husky/Fumadocs 配置

---

## 🔐 基础设施访问

项目除了 GitHub 仓库,还有几个对外/对内服务。所有登录都走**同一个 GitHub 账号**,不再有每处独立密码。

### 服务一览

| 用途 | URL | 谁能进 | 登录方式 |
| ------------ | ----------------------------------------------- | --------------------------------------- | --------------------------------------- |
| 主站 | `https://involutionhell.com` | 所有登录用户 | GitHub OAuth |
| 后端 API | `https://api.involutionhell.com` | — (内部调用) | sa-token (cookie/header) |
| **密钥管理** | `https://secrets.involutionhell.com` | **所有登录协作者**,按 project 权限查看 | GitHub OAuth(复用主站 App) |
| 数据库管理 | `https://api.involutionhell.com/admin/pgadmin/` | **仅 admin** | 主站 cookie 自动通过 Caddy forward_auth |
| 网站分析 | `https://umami.involutionhell.com` | **仅 admin** | 本地 umami 账号 |

### 怎么拿到 admin / 密钥权限

1. **申请 admin 角色**:现有 superadmin 在 `/admin/users` 页面勾选即可授予(产品规则:superadmin 本身不能通过 API 变动)
2. **申请 Infisical 项目访问**:登录 `secrets.involutionhell.com` 后(GitHub OAuth 自动建账号),联系现有 admin 加到对应 project。Infisical 内部按 environment 分 `dev` / `prod` / `shared`
3. **不要自己手动 INSERT `user_accounts` 表挂 admin 角色** —— OAuth 登录按 `github_<id>` 匹配 username,手工 insert 的人类 username 行永远是孤儿,用户登录后会另开一行丢 admin。历史上有人踩过

### `.env` 文件规则

- 本地 dev:
- 后端:`involution-hell-project/backend/.env`(`set -a && . ./.env && set +a` 注入 Spring Boot)
- 前端:`involution-hell-project/frontend/.env`
- 生产:`/home/ubuntu/involution-hell/.env`(**只在部署机**,不在仓库里;CI 不覆盖)
Comment on lines +374 to +377
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里新增的 .env 路径写的是 involution-hell-project/backend/.envinvolution-hell-project/frontend/.env,但这些目录在当前仓库中不存在。建议明确说明这是“另一个仓库/部署目录”的路径并给出链接,或改为当前仓库的实际路径,避免贡献者照做找不到文件。

Suggested change
- 本地 dev:
- 后端:`involution-hell-project/backend/.env``set -a && . ./.env && set +a` 注入 Spring Boot)
- 前端:`involution-hell-project/frontend/.env`
- 生产:`/home/ubuntu/involution-hell/.env`**只在部署机**,不在仓库里;CI 不覆盖)
- 下面提到的本地 dev 路径是**外部工作区 / 联动项目目录**中的 `.env` 位置示例,**不是当前仓库内一定存在的目录**;如果你当前检出的就是本文档所在仓库,请不要在本仓库根目录下寻找 `involution-hell-project/`
- 本地 dev:
- 后端:`involution-hell-project/backend/.env`(外部工作区路径;`set -a && . ./.env && set +a` 注入 Spring Boot)
- 前端:`involution-hell-project/frontend/.env`(外部工作区路径)
- 生产:`/home/ubuntu/involution-hell/.env`**只在部署机**,不在当前仓库里;CI 不覆盖)

Copilot uses AI. Check for mistakes.
- 两份 .env **故意有差异**(PGHOST / SERVER_PORT / AUTH_URL)—— 不要强行统一,参见 wiki [Changelog 2026-04-17](https://github.com/InvolutionHell/involutionhell/wiki/Changelog-2026-04-17-Self-Hosted-Infra) 的架构说明
- **所有秘密值**将来会迁到 Infisical 单一真源,`.env` 只存极少数 bootstrap 配置。改动期间前后仓两份并存,改值要同步改两处

### 开发者自助入口

登录主站后,访问**自己**的个人主页 `/u/<你的 github id>`,在顶部按钮栏能看到:

- **密钥管理 ↗**(本人访问自己主页时可见) → 跳 Infisical
- **管理员界面**(仅 admin 本人访问自己主页时可见) → 跳 `/admin`
- **编辑**(仅本人访问自己主页时可见) → 跳 profile 编辑

三个按钮都走 "只有本人看自己主页时才渲染",路人和其他登录用户在这里看不到。
Comment on lines +385 to +389
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

“开发者自助入口”这里列出的按钮顺序与页面实际按钮栏顺序不一致:页面是“编辑 → 密钥管理 → 管理员界面 → 排行”(见 app/u/[username]/page.tsx),但文档这里把“编辑”放在最后。建议把列表顺序调整为与 UI 一致,减少读者困惑。

Suggested change
- **密钥管理 ↗**(本人访问自己主页时可见) → 跳 Infisical
- **管理员界面**(仅 admin 本人访问自己主页时可见) → 跳 `/admin`
- **编辑**(仅本人访问自己主页时可见) → 跳 profile 编辑
三个按钮都走 "只有本人看自己主页时才渲染",路人和其他登录用户在这里看不到。
- **编辑**(仅本人访问自己主页时可见) → 跳 profile 编辑
- **密钥管理 ↗**(本人访问自己主页时可见) → 跳 Infisical
- **管理员界面**(仅 admin 本人访问自己主页时可见) → 跳 `/admin`
- **排行** → 跳个人主页排行视图
四个按钮里,**编辑****密钥管理****管理员界面**都走 "只有本人看自己主页时才渲染",路人和其他登录用户在这里看不到。

Copilot uses AI. Check for mistakes.
**但 Infisical 站本身** (`secrets.involutionhell.com`) **对所有登录协作者开放** ——
入口按钮只是 UX 便利,不影响访问权(路人可以直接敲地址栏进入)。

### Spring Boot 后端本地启动

```bash
cd involution-hell-project/backend
set -a && . ./.env && set +a # .env 里有 SERVER_PORT=8081 等
./mvnw spring-boot:run
Comment on lines +396 to +398
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里的后端启动步骤 cd involution-hell-project/backend 指向的目录在当前仓库中不存在。建议补充说明后端代码所在仓库/目录与获取方式(或移除该段落),否则贡献者按文档操作会直接失败。

Copilot uses AI. Check for mistakes.
```

前端 `BACKEND_URL` 指 `http://localhost:8081`,前后一致。

---

## 📚 文档规范

所有文档放在 `docs/` 目录。
Expand Down
49 changes: 49 additions & 0 deletions app/u/[username]/DeveloperToolsIfOwner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"use client";

/**
* 个人主页的"开发者选项"入口块。
*
* 和 AdminLinkIfOwnerAdmin 的区别——这里**不限 admin**,只要是主页 owner(当前登录
* 用户 === 这个主页本人)就看得见。理由:
* - 密钥管理 (Infisical) 是每个开发者都要用的,不是管理员专属。
* Infisical 自己按 project / environment 做权限细分,进去后看不到自己没权限的 secrets。
* - 以后其他"个人开发者工具"(比如 CI tokens、个人 API key 管理)也可以挂在这里
*
* 渲染条件:
* 1. 已登录
* 2. 当前登录用户就是这个主页的 owner(路人看不到)
*
* 注意:单独加 Link 而不是走 AdminGuard 风格,因为这是"入口按钮"不是"整页权限",
* 二次校验由目标服务(Infisical)自己做。
*/

import Link from "next/link";
import { useAuth } from "@/lib/use-auth";

interface Props {
ownerGithubId: number | null;
ownerUsername: string;
}

export function DeveloperToolsIfOwner({ ownerGithubId, ownerUsername }: Props) {
const { user, status } = useAuth();
if (status !== "authenticated" || !user) return null;

const isOwner =
(ownerGithubId != null && user.githubId === ownerGithubId) ||
user.username === ownerUsername;
if (!isOwner) return null;

return (
<Link
href="https://secrets.involutionhell.com"
target="_blank"
rel="noopener noreferrer"
className="font-mono text-[11px] uppercase tracking-widest px-2 py-1 border border-[var(--foreground)] text-[var(--foreground)] hover:bg-[var(--foreground)] hover:text-[var(--background)] transition-colors font-bold"
data-umami-event="profile_devtools_secrets_click"
title="Infisical 密钥管理(GitHub OAuth 登录,按 project 权限查看)"
Comment on lines +39 to +44
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

secrets.involutionhell.com*.involutionhell.com 子域;而当前登录态会把 satoken 写成 Domain=.involutionhell.com 的非 HttpOnly cookie(见 lib/use-auth.tsxsyncTokenCookie)。这意味着用户点击这里会把站内会话 token 自动带到 secrets 子域,并可能被该子域上的前端脚本读取/泄露。建议:尽量把密钥管理放到不共享该 cookie 的独立域名,或将 satoken cookie 的 Domain 收窄到仅 api.involutionhell.com(专供 pgAdmin forward_auth 场景),避免扩大 token 暴露面。

Copilot uses AI. Check for mistakes.
>
密钥管理 ↗
</Link>
);
}
7 changes: 7 additions & 0 deletions app/u/[username]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Footer } from "@/app/components/Footer";
import { ProfileCard } from "./ProfileCard";
import { EditLinkIfOwner } from "./EditLinkIfOwner";
import { AdminLinkIfOwnerAdmin } from "./AdminLinkIfOwnerAdmin";
import { DeveloperToolsIfOwner } from "./DeveloperToolsIfOwner";
import { ActivityHeatmap } from "./ActivityHeatmap";
import { FollowButton } from "./FollowButton";
import { GithubRepos, GithubReposSkeleton } from "./GithubRepos";
Expand Down Expand Up @@ -411,6 +412,12 @@ export default async function UserProfilePage({ params }: Param) {
ownerUsername={user.username}
identifier={username}
/>
{/* 开发者工具入口(所有本人都看得见;权限由目标服务自己管):
目前只有 Infisical 密钥管理,未来可挂 CI token / API key 等 */}
<DeveloperToolsIfOwner
ownerGithubId={user.githubId ?? null}
ownerUsername={user.username}
/>
{/* 管理员自见入口:只有 roles=admin 的本人访问自己主页时才渲染 */}
<AdminLinkIfOwnerAdmin
ownerGithubId={user.githubId ?? null}
Expand Down
Loading