Skip to content
Merged
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
9 changes: 9 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ jobs:
cache
pagination
mail
migrations
metrics
problem
)
for mod in "${modules[@]}"; do
echo "::group::go vet: $mod"
Expand Down Expand Up @@ -110,6 +113,9 @@ jobs:
cache
pagination
mail
migrations
metrics
problem
)
failed=0
for mod in "${modules[@]}"; do
Expand Down Expand Up @@ -158,6 +164,9 @@ jobs:
cache
pagination
mail
migrations
metrics
problem
)
for mod in "${modules[@]}"; do
echo "::group::go build: $mod"
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ jobs:
cache
pagination
mail
migrations
metrics
problem
)

for mod in "${modules[@]}"; do
Expand Down
17 changes: 10 additions & 7 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@

## Project Description

Scion is a copy-paste code library for Go backend development. It contains 12 self-contained modules in `registry/` — each is a standalone Go package. Modules are standard-library only by default; security-sensitive modules may be declared as `stdlibOnly:false` in `registry/index.json` and copied in standalone mode. Modules are meant to be copied into a user's project and adapted, not imported as a dependency.
Scion is a copy-paste code library for Go backend development. It contains 15 self-contained modules in `registry/` — each is a standalone Go package. Modules are standard-library only by default; security-sensitive or observability modules may be declared as `stdlibOnly:false` in `registry/index.json` and copied in standalone mode. Modules are meant to be copied into a user's project and adapted, not imported as a dependency.

## Coding Standards

- Go 1.22+ with generics
- Standard library only by default; declared `stdlibOnly:false` modules may use mature security libraries
- Standard library only by default; declared `stdlibOnly:false` modules may use mature security or observability libraries
- `gofmt` formatting is mandatory
- `go vet` must pass with zero warnings
- Middleware signature: `func(http.Handler) http.Handler`
Expand Down Expand Up @@ -63,13 +63,13 @@ cd registry/<module>/src/go && go test -v -count=1 ./...

```bash
# PowerShell
$modules = @('middleware','auth','crud','database','rbac','ratelimit','validation','file-upload','health','cache','pagination','mail')
$modules = @('middleware','auth','crud','database','rbac','ratelimit','validation','file-upload','health','cache','pagination','mail','migrations','metrics','problem')
foreach ($m in $modules) { Push-Location "registry/$m/src/go"; go test ./...; Pop-Location }
```

## Key Constraints

- Do NOT add external dependencies to any module's `go.mod` unless the module is explicitly marked `stdlibOnly:false` in `registry/index.json` and the dependency is justified for security or correctness
- Do NOT add external dependencies to any module's `go.mod` unless the module is explicitly marked `stdlibOnly:false` in `registry/index.json` and the dependency is justified for security, correctness, or observability
- Do NOT use `panic` in HTTP handlers — return errors
- Do NOT trust client headers (`Content-Type`, `X-Forwarded-For`, `X-Real-Ip`)
- Do NOT use `strings.Split` for header parsing — use `strings.SplitN` with a limit
Expand All @@ -89,7 +89,7 @@ You are working on Scion, a copy-paste code library for Go backend development.
Project location: <path-to-scion>

Architecture:
- 12 modules in registry/ — each is a standalone Go package
- 15 modules in registry/ — each is a standalone Go package
- Module path pattern: registry/<module>/src/go/
- Go 1.22+, standard library by default, gofmt mandatory

Expand Down Expand Up @@ -125,7 +125,7 @@ Task: <describe your task here>

```
scion/
├── registry/ # 12 copy-paste modules
├── registry/ # 15 copy-paste modules
│ ├── auth/ # JWT auth + bcrypt
│ ├── crud/ # Generic CRUD + pagination
│ ├── database/ # database/sql helpers
Expand All @@ -137,7 +137,10 @@ scion/
│ ├── health/ # Liveness/readiness probes
│ ├── cache/ # TTL + LRU cache
│ ├── pagination/ # Offset + cursor pagination
│ └── mail/ # SMTP email sender
│ ├── mail/ # SMTP email sender
│ ├── migrations/ # SQL migration runner
│ ├── metrics/ # Prometheus HTTP metrics
│ └── problem/ # RFC 9457 problem responses
├── docs/ # Human-readable docs
├── AGENTS.md # This file (English)
├── AGENTS_zh.md # This file (Chinese)
Expand Down
17 changes: 10 additions & 7 deletions AGENTS_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@

## 项目描述

Scion 是一个面向 Go 后端开发的复制粘贴代码库。`registry/` 目录下有 12 个自包含模块,每个都是独立的 Go 包。模块默认仅使用标准库;安全敏感模块可以在 `registry/index.json` 中显式标记为 `stdlibOnly:false`,并以 standalone 模式复制。模块的设计目的是被复制到用户项目中并适配,而非作为依赖导入。
Scion 是一个面向 Go 后端开发的复制粘贴代码库。`registry/` 目录下有 15 个自包含模块,每个都是独立的 Go 包。模块默认仅使用标准库;安全敏感或可观测性模块可以在 `registry/index.json` 中显式标记为 `stdlibOnly:false`,并以 standalone 模式复制。模块的设计目的是被复制到用户项目中并适配,而非作为依赖导入。

## 编码标准

- Go 1.22+,使用泛型
- 默认仅使用标准库;显式标记为 `stdlibOnly:false` 的模块可以使用成熟安全库
- 默认仅使用标准库;显式标记为 `stdlibOnly:false` 的模块可以使用成熟安全或可观测性库
- `gofmt` 格式化是强制的
- `go vet` 必须零警告通过
- 中间件签名:`func(http.Handler) http.Handler`
Expand Down Expand Up @@ -63,13 +63,13 @@ cd registry/<module>/src/go && go test -v -count=1 ./...

```bash
# PowerShell
$modules = @('middleware','auth','crud','database','rbac','ratelimit','validation','file-upload','health','cache','pagination','mail')
$modules = @('middleware','auth','crud','database','rbac','ratelimit','validation','file-upload','health','cache','pagination','mail','migrations','metrics','problem')
foreach ($m in $modules) { Push-Location "registry/$m/src/go"; go test ./...; Pop-Location }
```

## 关键约束

- 不要给任何模块的 `go.mod` 添加外部依赖,除非该模块已在 `registry/index.json` 显式标记为 `stdlibOnly:false`,且依赖对安全或正确性有明确价值
- 不要给任何模块的 `go.mod` 添加外部依赖,除非该模块已在 `registry/index.json` 显式标记为 `stdlibOnly:false`,且依赖对安全、正确性或可观测性有明确价值
- 不要在 HTTP 处理器中使用 `panic` — 返回错误
- 不要信任客户端 header(`Content-Type`、`X-Forwarded-For`、`X-Real-Ip`)
- 不要用 `strings.Split` 解析 header — 用 `strings.SplitN` 加限制
Expand All @@ -89,7 +89,7 @@ foreach ($m in $modules) { Push-Location "registry/$m/src/go"; go test ./...; Po
项目路径: <scion-项目路径>

架构:
- registry/ 下有 12 个模块 — 每个是独立的 Go 包
- registry/ 下有 15 个模块 — 每个是独立的 Go 包
- 模块路径模式: registry/<模块名>/src/go/
- Go 1.22+,默认仅使用标准库,gofmt 强制

Expand Down Expand Up @@ -125,7 +125,7 @@ foreach ($m in $modules) { Push-Location "registry/$m/src/go"; go test ./...; Po

```
scion/
├── registry/ # 12 个复制粘贴模块
├── registry/ # 15 个复制粘贴模块
│ ├── auth/ # JWT 认证 + bcrypt
│ ├── crud/ # 泛型 CRUD + 分页
│ ├── database/ # database/sql 工具
Expand All @@ -137,7 +137,10 @@ scion/
│ ├── health/ # 存活/就绪探针
│ ├── cache/ # TTL + LRU 缓存
│ ├── pagination/ # Offset + cursor 分页
│ └── mail/ # SMTP 邮件发送
│ ├── mail/ # SMTP 邮件发送
│ ├── migrations/ # SQL 迁移执行器
│ ├── metrics/ # Prometheus HTTP 指标
│ └── problem/ # RFC 9457 错误响应
├── docs/ # 人类可读文档
├── AGENTS.md # 本文件(英文)
├── AGENTS_zh.md # 本文件(中文)
Expand Down
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ scion diff cache

When `--to` or `--target` is omitted, Scion uses the module's default target, such as `internal/cache`. You can still override it with `--to <dir>` or `--target <dir>`.

Scion copies source files and writes `.scion-module.json` metadata for later comparison. It never edits your project's `go.mod` automatically. Modules marked `stdlibOnly=false`, such as `auth`, require explicit standalone mode:
Scion copies source files and writes `.scion-module.json` metadata for later comparison. It never edits your project's `go.mod` automatically. Modules marked `stdlibOnly=false`, such as `auth` and `metrics`, require explicit standalone mode:

```bash
scion add auth --standalone
Expand Down Expand Up @@ -84,6 +84,9 @@ Backend modules such as auth, CRUD, file upload, and rate limiting share most of
| [cache](registry/cache/) | Generic TTL + LRU cache | Background cleanup, goroutine leak prevention, max entries limit |
| [pagination](registry/pagination/) | Offset/limit + cursor pagination | Cursor base64 validation, negative offset clamp, max limit enforcement |
| [mail](registry/mail/) | SMTP email with templates | Header injection prevention, XSS escaping, attachment sanitization, async queue |
| [migrations](registry/migrations/) | SQL migration runner | Safe filenames, table whitelist, checksums, transactions |
| [metrics](registry/metrics/) | Prometheus HTTP metrics | Route cardinality limits, label sanitization, isolated registry |
| [problem](registry/problem/) | RFC 9457 problem responses | CRLF/null rejection, detail truncation, panic recovery |

## CLI Commands

Expand Down Expand Up @@ -114,8 +117,11 @@ scion/
| |-- file-upload/ # File upload handler
| |-- health/ # Health check probes
| |-- mail/ # SMTP email sender
| |-- metrics/ # Prometheus HTTP metrics
| |-- migrations/ # SQL migration runner
| |-- middleware/ # HTTP middleware collection
| |-- pagination/ # Pagination utilities
| |-- problem/ # Problem Details API errors
| |-- ratelimit/ # Rate limiting algorithms
| |-- rbac/ # Role-based access control
| `-- validation/ # Request validation builder
Expand Down Expand Up @@ -145,7 +151,7 @@ go run ./cmd/scion doctor --strict
Run tests for all registry modules in PowerShell:

```powershell
$modules = @('middleware','auth','crud','database','rbac','ratelimit','validation','file-upload','health','cache','pagination','mail')
$modules = @('middleware','auth','crud','database','rbac','ratelimit','validation','file-upload','health','cache','pagination','mail','migrations','metrics','problem')
foreach ($m in $modules) { Push-Location "registry/$m/src/go"; go test ./...; Pop-Location }
```

Expand Down
10 changes: 8 additions & 2 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ scion diff cache

省略 `--to` 或 `--target` 时,Scion 会使用模块的默认目标目录,例如 `internal/cache`。你仍然可以用 `--to <dir>` 或 `--target <dir>` 覆盖。

Scion CLI 会复制源码,并写入 `.scion-module.json` 供后续对比使用。它不会自动修改你的 `go.mod`。标记为 `stdlibOnly=false` 的模块,例如 `auth`,需要显式使用 standalone 模式:
Scion CLI 会复制源码,并写入 `.scion-module.json` 供后续对比使用。它不会自动修改你的 `go.mod`。标记为 `stdlibOnly=false` 的模块,例如 `auth` 和 `metrics`,需要显式使用 standalone 模式:

```bash
scion add auth --standalone
Expand Down Expand Up @@ -84,6 +84,9 @@ Get-FileHash .\scion_v0.1.3_windows_amd64.zip -Algorithm SHA256
| [cache](registry/cache/) | 泛型 TTL + LRU 缓存 | 后台清理、goroutine 泄漏防护、最大条目数限制 |
| [pagination](registry/pagination/) | Offset/limit + cursor 分页 | cursor base64 校验、负 offset 归零、最大 limit 限制 |
| [mail](registry/mail/) | SMTP 邮件 + 模板 | 邮件头注入防护、XSS 转义、附件净化、异步队列 |
| [migrations](registry/migrations/) | SQL 迁移执行器 | 安全文件名、表名白名单、checksum、事务 |
| [metrics](registry/metrics/) | Prometheus HTTP 指标 | 路由基数限制、label 净化、隔离 registry |
| [problem](registry/problem/) | RFC 9457 错误响应 | CRLF/null 拒绝、detail 截断、panic 恢复 |

## CLI 命令

Expand Down Expand Up @@ -114,8 +117,11 @@ scion/
| |-- file-upload/ # 文件上传模块
| |-- health/ # 健康检查模块
| |-- mail/ # SMTP 邮件模块
| |-- metrics/ # Prometheus HTTP 指标
| |-- migrations/ # SQL 迁移执行器
| |-- middleware/ # HTTP 中间件集合
| |-- pagination/ # 分页工具
| |-- problem/ # Problem Details API 错误
| |-- ratelimit/ # 限流算法
| |-- rbac/ # 角色权限控制
| `-- validation/ # 请求校验构建器
Expand Down Expand Up @@ -145,7 +151,7 @@ go run ./cmd/scion doctor --strict
PowerShell 中运行所有 registry 模块测试:

```powershell
$modules = @('middleware','auth','crud','database','rbac','ratelimit','validation','file-upload','health','cache','pagination','mail')
$modules = @('middleware','auth','crud','database','rbac','ratelimit','validation','file-upload','health','cache','pagination','mail','migrations','metrics','problem')
foreach ($m in $modules) { Push-Location "registry/$m/src/go"; go test ./...; Pop-Location }
```

Expand Down
10 changes: 8 additions & 2 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ export default defineConfig({
{ text: 'Health', link: '/modules/health' },
{ text: 'Cache', link: '/modules/cache' },
{ text: 'Pagination', link: '/modules/pagination' },
{ text: 'Mail', link: '/modules/mail' }
{ text: 'Mail', link: '/modules/mail' },
{ text: 'Migrations', link: '/modules/migrations' },
{ text: 'Metrics', link: '/modules/metrics' },
{ text: 'Problem Details', link: '/modules/problem' }
]
}
]
Expand Down Expand Up @@ -95,7 +98,10 @@ export default defineConfig({
{ text: 'Health 健康检查', link: '/zh/modules/health' },
{ text: 'Cache 缓存', link: '/zh/modules/cache' },
{ text: 'Pagination 分页', link: '/zh/modules/pagination' },
{ text: 'Mail 邮件', link: '/zh/modules/mail' }
{ text: 'Mail 邮件', link: '/zh/modules/mail' },
{ text: 'Migrations 迁移', link: '/zh/modules/migrations' },
{ text: 'Metrics 指标', link: '/zh/modules/metrics' },
{ text: 'Problem Details 错误响应', link: '/zh/modules/problem' }
]
}
]
Expand Down
4 changes: 2 additions & 2 deletions docs/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Add your module to `registry/index.json`.
## Code Standards

- Go 1.22+ with generics
- Standard library only by default; external dependencies require an explicit `stdlibOnly:false` registry entry and security/correctness justification
- Standard library only by default; external dependencies require an explicit `stdlibOnly:false` registry entry and security/correctness/observability justification
- `gofmt` formatting
- `go vet` must pass
- Middleware signature: `func(http.Handler) http.Handler`
Expand All @@ -66,7 +66,7 @@ Add your module to `registry/index.json`.
cd registry/<module>/src/go && go test -v ./...

# Test all modules
$modules = @('middleware','auth','crud','database','rbac','ratelimit','validation','file-upload','health','cache','pagination','mail')
$modules = @('middleware','auth','crud','database','rbac','ratelimit','validation','file-upload','health','cache','pagination','mail','migrations','metrics','problem')
foreach ($m in $modules) { Push-Location "registry/$m/src/go"; go test ./...; Pop-Location }
```

Expand Down
12 changes: 12 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,18 @@ features:
title: Mail
details: SMTP email with templates, header injection prevention, and async queue.
link: /modules/mail
- icon: SQL
title: Migrations
details: SQL migration runner with checksums, transactions, and safe file validation.
link: /modules/migrations
- icon: 📈
title: Metrics
details: Prometheus HTTP metrics with route cardinality limits and label sanitization.
link: /modules/metrics
- icon: ⚠️
title: Problem Details
details: RFC 9457 API error responses with panic recovery and safe details.
link: /modules/problem
---

## Quick Start
Expand Down
7 changes: 5 additions & 2 deletions docs/modules/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Modules Overview

Scion provides 12 production-ready, copy-paste Go modules. Each module is self-contained. Modules are standard-library only by default; declared security exceptions are marked in the registry.
Scion provides 15 production-ready, copy-paste Go modules. Each module is self-contained. Modules are standard-library only by default; declared security and observability exceptions are marked in the registry.

## Available Modules

Expand All @@ -18,6 +18,9 @@ Scion provides 12 production-ready, copy-paste Go modules. Each module is self-c
| [Cache](/modules/cache) | TTL + LRU in-memory cache | Background cleanup, max entries limit |
| [Pagination](/modules/pagination) | Offset/cursor pagination | Cursor base64 validation, max limit enforcement |
| [Mail](/modules/mail) | SMTP email with templates | Header injection prevention, XSS escaping |
| [Migrations](/modules/migrations) | SQL migration runner | Safe filenames, table whitelist, checksums |
| [Metrics](/modules/metrics) | Prometheus HTTP metrics | Route cardinality limits, label sanitization |
| [Problem Details](/modules/problem) | RFC 9457 API errors | CRLF/null rejection, panic recovery |

## Quick Copy

Expand Down Expand Up @@ -54,4 +57,4 @@ go test -v ./...

## Dependencies

Modules use only the Go standard library by default. Declared exceptions, such as auth, copy their own `go.mod` in standalone mode.
Modules use only the Go standard library by default. Declared exceptions, such as auth and metrics, copy their own `go.mod` in standalone mode.
40 changes: 40 additions & 0 deletions docs/modules/metrics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Metrics Module

Prometheus HTTP metrics for `net/http` services.

## Features

- Isolated Prometheus registry
- Request counter, duration histogram, and in-flight gauge
- `/metrics` scrape handler
- `func(http.Handler) http.Handler` middleware
- Optional Go runtime/process collectors

## Usage

```go
m, err := metrics.New()
if err != nil {
return err
}
_ = m.RegisterDefaults()

http.Handle("/metrics", m.Handler())
http.Handle("/users/", m.Middleware("/users/{id}")(usersHandler))
```

Pass route templates, not raw URLs.

## Security

- Rejects CRLF and null bytes in labels
- Normalizes raw URLs and overlong labels
- Caps route-label cardinality and sends overflow to `route="overflow"`

## Copy

`metrics` uses Prometheus, so copy it in standalone mode:

```bash
scion add metrics --standalone --to internal/metrics
```
Loading
Loading