diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..99c0129 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,196 @@ +name: Release + +on: + push: + tags: + - "v*.*.*" + workflow_dispatch: + inputs: + tag: + description: "Release tag, for example v0.1.2" + required: true + type: string + +permissions: + contents: write + +concurrency: + group: release-${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }} + cancel-in-progress: false + +jobs: + release: + name: Build and publish release + runs-on: ubuntu-latest + steps: + - name: Resolve tag + id: release + shell: bash + run: | + set -euo pipefail + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + tag="${{ inputs.tag }}" + else + tag="${{ github.ref_name }}" + fi + if [[ ! "$tag" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "::error::Release tag must match vMAJOR.MINOR.PATCH, got: $tag" + exit 1 + fi + echo "tag=$tag" >> "$GITHUB_OUTPUT" + + - name: Checkout tag + uses: actions/checkout@v4 + with: + ref: ${{ steps.release.outputs.tag }} + fetch-depth: 0 + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: "1.22" + + - name: Resolve release commit + id: commit + shell: bash + run: | + set -euo pipefail + tag="${{ steps.release.outputs.tag }}" + sha="$(git rev-list -n 1 "$tag")" + echo "sha=$sha" >> "$GITHUB_OUTPUT" + + - name: Ensure release does not already exist + env: + GH_TOKEN: ${{ github.token }} + shell: bash + run: | + set -euo pipefail + tag="${{ steps.release.outputs.tag }}" + if gh release view "$tag" >/dev/null 2>&1; then + echo "::error::Release already exists: $tag" + exit 1 + fi + + - name: Run release gates + shell: bash + run: | + set -euo pipefail + echo "::group::root tests" + go test -count=1 -timeout 10m ./cmd/... ./internal/... + echo "::endgroup::" + + echo "::group::root vet" + go vet ./cmd/... ./internal/... + echo "::endgroup::" + + echo "::group::doctor strict" + go run ./cmd/scion doctor --strict + echo "::endgroup::" + + echo "::group::bundle freshness" + go run ./internal/cmd/build-bundle + git diff --exit-code -- internal/bundle + echo "::endgroup::" + + - name: Build release assets + shell: bash + run: | + set -euo pipefail + tag="${{ steps.release.outputs.tag }}" + sha="${{ steps.commit.outputs.sha }}" + ldflags="-s -w -X github.com/DarkInno/scion/internal/version.Version=$tag -X github.com/DarkInno/scion/internal/version.Commit=$sha" + + rm -rf dist + mkdir -p dist + + targets=( + "linux amd64 tar.gz" + "linux arm64 tar.gz" + "darwin amd64 tar.gz" + "darwin arm64 tar.gz" + "windows amd64 zip" + "windows arm64 zip" + ) + + for target in "${targets[@]}"; do + read -r goos goarch archive <<< "$target" + name="scion_${tag}_${goos}_${goarch}" + stage="dist/$name" + mkdir -p "$stage" + + ext="" + if [ "$goos" = "windows" ]; then + ext=".exe" + fi + + echo "::group::build $goos/$goarch" + CGO_ENABLED=0 GOOS="$goos" GOARCH="$goarch" \ + go build -trimpath -ldflags "$ldflags" -o "$stage/scion$ext" ./cmd/scion + cp LICENSE "$stage/LICENSE" + cp README.md "$stage/README.md" + + if [ "$archive" = "zip" ]; then + (cd "$stage" && zip -q -r "../$name.zip" .) + else + tar -czf "dist/$name.tar.gz" -C "$stage" . + fi + echo "::endgroup::" + done + + (cd dist && sha256sum scion_*.tar.gz scion_*.zip > SHA256SUMS) + + - name: Verify built binary version + shell: bash + run: | + set -euo pipefail + tag="${{ steps.release.outputs.tag }}" + version="$(./dist/scion_${tag}_linux_amd64/scion version)" + echo "$version" + grep -q "scion $tag" <<< "$version" + grep -q "commit: ${{ steps.commit.outputs.sha }}" <<< "$version" + + - name: Write release notes + shell: bash + run: | + set -euo pipefail + tag="${{ steps.release.outputs.tag }}" + cat > release-notes.md < Graft backend patterns into your project. Copy-paste, not install. +> Graft backend patterns into your project. Copy source, not dependencies. [English](README.md) | [中文](README_zh.md) -Scion is a copy-paste code library for Go backend development. Instead of installing a framework or pulling a dependency, you copy pre-built, production-ready modules into your project and own every line of code. +Scion is a copy-paste code library for Go backend development. It ships production-oriented modules as source templates, so you can copy them into your project, adapt them, and own every line. -## Why Copy-Paste? +## Quick Start -Backend modules (auth, CRUD, file upload, rate limiting) share 80% of their skeleton across projects, but the remaining 20% differs in ways that make npm/go packages awkward: +Install the CLI with Go 1.22 or newer: -- You need to customize business logic deep inside the module -- You want to own the code, not be locked to upstream versions -- Your AI coding assistant works better with code it can read and modify directly -- No dependency hell — standard library by default, with declared security exceptions +```bash +go install github.com/DarkInno/scion/cmd/scion@latest +``` -## Quick Start +For reproducible installs, pin a release: ```bash -# 1. Install the source-template copier -go install github.com/DarkInno/scion/cmd/scion@latest +go install github.com/DarkInno/scion/cmd/scion@v0.1.2 +``` -# 2. Copy a zero-dependency module into your project -scion add cache --to internal/cache +Make sure your Go bin directory is on `PATH`, then verify the install: + +```bash +scion version +scion list +``` + +Copy a standard-library-only module into your project: -# 3. Inspect local changes against the embedded template later +```bash +scion add cache --to internal/cache --dry-run +scion add cache --to internal/cache scion diff cache --target internal/cache ``` -Scion's CLI copies source files and writes `.scion-module.json` metadata for later comparison. It never edits your `go.mod` automatically. Modules marked `stdlibOnly=false` must be copied with `--standalone` so their `go.mod`/`go.sum` are explicit. +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: + +```bash +scion add auth --standalone --to internal/auth +``` + +## Binary Downloads + +Prebuilt binaries are available on the [GitHub Releases](https://github.com/DarkInno/scion/releases) page for macOS, Linux, and Windows on amd64 and arm64. -Manual copy still works: +Verify a downloaded asset with `SHA256SUMS`: ```bash -# 1. Copy a module into your project -cp -r registry/cache/src/go/*.go yourproject/internal/cache/ +sha256sum -c SHA256SUMS +``` + +On Windows PowerShell: -# 2. Adapt the package to your project -# Rename, trim tests, or wire it into your service as needed. +```powershell +Get-FileHash .\scion_v0.1.2_windows_amd64.zip -Algorithm SHA256 ``` +## Why Copy-Paste? + +Backend modules such as auth, CRUD, file upload, and rate limiting share most of their structure across projects, but the last mile is usually project-specific: + +- You need to customize business logic inside the module. +- You want to own the code instead of being locked to upstream APIs. +- AI coding assistants work better with source they can read and edit directly. +- Scion avoids dependency sprawl by default; security-sensitive exceptions are declared explicitly. + ## Available Modules | Module | Description | Security Features | @@ -49,79 +75,84 @@ cp -r registry/cache/src/go/*.go yourproject/internal/cache/ | [middleware](registry/middleware/) | Recovery, CORS, logging, timeout, etc. | CRLF injection prevention, trusted proxy, body size limit | | [rbac](registry/rbac/) | Role-based access control | Wildcard permissions, cycle detection, hierarchy inheritance | | [ratelimit](registry/ratelimit/) | Fixed window / sliding window / token bucket | Memory exhaustion protection, LRU eviction, key length limit | -| [validation](registry/validation/) | Chainable request validation builder | Regex DoS prevention (RE2), null byte/CRLF rejection, panic recovery | +| [validation](registry/validation/) | Chainable request validation builder | Regex DoS prevention, null byte/CRLF rejection, panic recovery | | [file-upload](registry/file-upload/) | Secure file upload handler | Magic bytes validation, path traversal prevention, size limit, rate limiting | -| [health](registry/health/) | Liveness/readiness probes | SSRF protection (private IP rejection), CRLF injection prevention | +| [health](registry/health/) | Liveness/readiness probes | SSRF protection, CRLF injection prevention | | [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 | -## Project Structure +## CLI Commands -``` -scion/ -├── registry/ -│ ├── index.json # Machine-readable module index -│ ├── auth/ # Authentication module -│ │ ├── __llms__.md # AI-readable summary (~150 tokens) -│ │ ├── README.md # Human-readable adaptation guide -│ │ ├── src/go/ # Go source code -│ │ └── examples/gin/ # Minimal runnable example -│ ├── crud/ # CRUD operations module -│ ├── middleware/ # HTTP middleware collection -│ ├── rbac/ # Role-based access control -│ ├── ratelimit/ # Rate limiting algorithms -│ ├── validation/ # Request validation builder -│ ├── file-upload/ # File upload handler -│ ├── health/ # Health check probes -│ ├── cache/ # In-memory cache -│ ├── pagination/ # Pagination utilities -│ └── mail/ # Email sender -├── docs/ -│ └── getting-started.md # How to use Scion -├── AGENTS.md # AI coding agent instructions -├── CONTRIBUTING.md # How to contribute -├── LICENSE # MIT -└── llms.txt # LLM-friendly project summary +```bash +scion list [--json] +scion info [--json] +scion add --to [--dry-run] [--force] [--standalone] +scion diff --target [--json] +scion doctor [--strict] [--json] +scion version [--json] ``` -## Design Principles +## Project Structure -1. **Code ownership** — every line is yours after copying. No upstream lock-in. -2. **Self-contained** — each module works independently; external dependencies are allowed only for declared security exceptions. -3. **Framework-agnostic** — uses Go standard `net/http`, adaptable to Gin/Echo/etc. -4. **Security-first** — input validation, rate limiting, injection prevention built in. -5. **AI-friendly** — `__llms__.md` files let AI assistants understand modules in ~200 tokens. -6. **Tested** — every module includes functional tests and penetration test cases. +```text +scion/ +|-- cmd/scion/ # CLI entrypoint +|-- internal/ # CLI implementation, bundle reader, doctor checks +|-- internal/bundle/ # Embedded registry bundle generated from registry/ +|-- registry/ +| |-- index.json # Machine-readable module index +| |-- auth/ # Authentication module +| |-- cache/ # TTL + LRU cache +| |-- crud/ # CRUD operations module +| |-- file-upload/ # File upload handler +| |-- health/ # Health check probes +| |-- mail/ # SMTP email sender +| |-- middleware/ # HTTP middleware collection +| |-- pagination/ # Pagination utilities +| |-- ratelimit/ # Rate limiting algorithms +| |-- rbac/ # Role-based access control +| `-- validation/ # Request validation builder +|-- docs/ # VitePress documentation +|-- AGENTS.md # AI coding agent instructions +|-- CONTRIBUTING.md # Contribution guide +`-- LICENSE # MIT +``` ## Development ```bash -# Clone the repository git clone https://github.com/DarkInno/scion.git cd scion # Regenerate the embedded CLI bundle after registry changes go run ./internal/cmd/build-bundle -# Test the root CLI +# Test and vet the root CLI go test ./cmd/... ./internal/... +go vet ./cmd/... ./internal/... + +# Run strict registry checks +go run ./cmd/scion doctor --strict +``` -# Run tests for a specific module -cd registry/auth/src/go && go test -v ./... +Run tests for all registry modules in PowerShell: -# Run tests for all modules -# (PowerShell) +```powershell $modules = @('middleware','auth','crud','rbac','ratelimit','validation','file-upload','health','cache','pagination','mail') foreach ($m in $modules) { Push-Location "registry/$m/src/go"; go test ./...; Pop-Location } - -# Format code -cd registry/auth/src/go && gofmt -w . ``` -## Contributing +## Releasing + +Releases are created from semantic version tags: + +```bash +git tag -a v0.1.2 -m "v0.1.2" +git push origin v0.1.2 +``` -We welcome contributions! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on adding new modules. +The release workflow verifies the CLI, rebuilds the embedded bundle check, cross-compiles binaries, generates `SHA256SUMS`, and publishes GitHub Release assets. ## License diff --git a/README_zh.md b/README_zh.md index c7f5f2d..73559c4 100644 --- a/README_zh.md +++ b/README_zh.md @@ -1,113 +1,159 @@ # Scion -> 将后端模式嫁接到你的项目中。复制粘贴,而非安装依赖。 +> 把后端常用模式嫁接到你的项目里:复制源码,而不是引入依赖。 [English](README.md) | [中文](README_zh.md) -Scion 是一个面向 Go 后端开发的复制粘贴代码库。你不需要安装框架或拉取依赖,只需将预构建的生产级模块复制到你的项目中,每一行代码都归你所有。 +Scion 是面向 Go 后端开发的复制粘贴式源码模板库。它把常见后端模块以源码模板的形式发布,你可以把模块复制进自己的项目,按业务改造,并最终拥有这些代码。 -## 为什么要复制粘贴? +## 快速开始 -后端模块(认证、CRUD、文件上传、限流)在不同项目中 80% 的骨架是相同的,但剩下的 20% 差异使得 npm/go 包变得别扭: +需要 Go 1.22 或更新版本: -- 你需要在模块深处自定义业务逻辑 -- 你想拥有代码的所有权,而不是被上游版本锁定 -- 你的 AI 编码助手在能直接阅读和修改代码时表现更好 -- 没有依赖地狱 — 默认仅使用 Go 标准库,安全例外会显式声明 +```bash +go install github.com/DarkInno/scion/cmd/scion@latest +``` -## 快速开始 +如果需要固定版本: ```bash -# 1. 将模块复制到你的项目中 -cp -r registry/auth/src/go/* yourproject/internal/auth/ +go install github.com/DarkInno/scion/cmd/scion@v0.1.2 +``` -# 2. 适配配置 -# 编辑 config.go:设置 JWT 密钥、数据库 URL 等 +确认 Go bin 目录已加入 `PATH`,然后验证安装: -# 3. 实现 Store 接口 -# type UserStore interface { ... } // 你的数据库层 +```bash +scion version +scion list +``` + +复制一个仅使用标准库的模块: -# 4. 注册路由 -# 参考 registry/auth/examples/gin/main.go +```bash +scion add cache --to internal/cache --dry-run +scion add cache --to internal/cache +scion diff cache --target internal/cache ``` +Scion CLI 会复制源码,并写入 `.scion-module.json` 供后续对比使用。它不会自动修改你的 `go.mod`。标记为 `stdlibOnly=false` 的模块,例如 `auth`,需要显式使用 standalone 模式: + +```bash +scion add auth --standalone --to internal/auth +``` + +## 二进制下载 + +预编译二进制可以在 [GitHub Releases](https://github.com/DarkInno/scion/releases) 下载,支持 macOS、Linux、Windows 的 amd64 和 arm64。 + +使用 `SHA256SUMS` 校验下载文件: + +```bash +sha256sum -c SHA256SUMS +``` + +Windows PowerShell: + +```powershell +Get-FileHash .\scion_v0.1.2_windows_amd64.zip -Algorithm SHA256 +``` + +## 为什么是复制粘贴? + +认证、CRUD、文件上传、限流等后端模块在不同项目里大部分结构相同,但最后一段总要贴合具体业务: + +- 你需要深入模块内部修改业务逻辑。 +- 你想拥有源码,而不是被上游包的 API 设计锁住。 +- AI 编码助手更擅长处理能直接读取和编辑的源码。 +- Scion 默认避免依赖膨胀;安全相关例外会在模块元数据中明确标记。 + ## 可用模块 | 模块 | 描述 | 安全特性 | -|------|------|---------| -| [auth](registry/auth/) | JWT 邮箱/密码认证 + bcrypt | 限流、用户枚举防护、JTI、aud/iss 验证 | +|------|------|----------| +| [auth](registry/auth/) | JWT 邮箱/密码认证 + bcrypt | 限流、用户枚举防护、JTI、aud/iss 校验 | | [crud](registry/crud/) | 泛型 CRUD + 分页 | 排序/过滤白名单、SQL 注入防护、分页上限 | | [middleware](registry/middleware/) | Recovery、CORS、日志、超时等 | CRLF 注入防护、可信代理、请求体大小限制 | | [rbac](registry/rbac/) | 基于角色的访问控制 | 通配符权限、循环检测、层级继承 | -| [ratelimit](registry/ratelimit/) | 固定窗口/滑动窗口/令牌桶 | 内存耗尽防护、LRU 驱逐、key 长度限制 | -| [validation](registry/validation/) | 链式请求验证构建器 | 正则 DoS 防护(RE2)、null 字节/CRLF 拒绝、panic 恢复 | -| [file-upload](registry/file-upload/) | 安全文件上传处理器 | magic bytes 验证、路径穿越防护、大小限制、限流 | -| [health](registry/health/) | 存活/就绪探针 | SSRF 防护(拒绝内网 IP)、CRLF 注入防护 | +| [ratelimit](registry/ratelimit/) | 固定窗口 / 滑动窗口 / 令牌桶 | 内存耗尽防护、LRU 驱逐、key 长度限制 | +| [validation](registry/validation/) | 链式请求校验构建器 | 正则 DoS 防护、拒绝 null 字节/CRLF、panic 恢复 | +| [file-upload](registry/file-upload/) | 安全文件上传处理器 | Magic bytes 校验、路径穿越防护、大小限制、限流 | +| [health](registry/health/) | 存活/就绪探针 | SSRF 防护、CRLF 注入防护 | | [cache](registry/cache/) | 泛型 TTL + LRU 缓存 | 后台清理、goroutine 泄漏防护、最大条目数限制 | -| [pagination](registry/pagination/) | Offset/limit + cursor 分页 | cursor base64 验证、负数 offset 归零、最大 limit 限制 | +| [pagination](registry/pagination/) | Offset/limit + cursor 分页 | cursor base64 校验、负 offset 归零、最大 limit 限制 | | [mail](registry/mail/) | SMTP 邮件 + 模板 | 邮件头注入防护、XSS 转义、附件净化、异步队列 | -## 项目结构 +## CLI 命令 -``` -scion/ -├── registry/ -│ ├── index.json # 机器可读的模块索引 -│ ├── auth/ # 认证模块 -│ │ ├── __llms__.md # AI 可读摘要(约 150 token) -│ │ ├── README.md # 人类可读适配指南 -│ │ ├── src/go/ # Go 源代码 -│ │ └── examples/gin/ # 最小可运行示例 -│ ├── crud/ # CRUD 操作模块 -│ ├── middleware/ # HTTP 中间件集合 -│ ├── rbac/ # 角色权限控制 -│ ├── ratelimit/ # 限流算法 -│ ├── validation/ # 请求验证构建器 -│ ├── file-upload/ # 文件上传处理器 -│ ├── health/ # 健康检查探针 -│ ├── cache/ # 内存缓存 -│ ├── pagination/ # 分页工具 -│ └── mail/ # 邮件发送 -├── docs/ -│ └── getting-started.md # 如何使用 Scion -├── AGENTS.md # AI 编码代理指令(英文) -├── AGENTS_zh.md # AI 编码代理指令(中文) -├── CONTRIBUTING.md # 贡献指南 -├── LICENSE # MIT -└── llms.txt # LLM 友好的项目摘要 +```bash +scion list [--json] +scion info [--json] +scion add --to [--dry-run] [--force] [--standalone] +scion diff --target [--json] +scion doctor [--strict] [--json] +scion version [--json] ``` -## 设计原则 +## 项目结构 -1. **代码所有权** — 复制后每一行代码都是你的,没有上游锁定。 -2. **自包含** — 每个模块独立工作;只有显式声明的安全例外才允许外部依赖。 -3. **框架无关** — 使用 Go 标准 `net/http`,可适配 Gin/Echo 等。 -4. **安全优先** — 内置输入验证、限流、注入防护。 -5. **AI 友好** — `__llms__.md` 文件让 AI 助手在约 200 token 内理解模块。 -6. **经过测试** — 每个模块包含功能测试和渗透测试用例。 +```text +scion/ +|-- cmd/scion/ # CLI 入口 +|-- internal/ # CLI 实现、bundle 读取、doctor 检查 +|-- internal/bundle/ # 从 registry/ 生成的内置模板包 +|-- registry/ +| |-- index.json # 机器可读模块索引 +| |-- auth/ # 认证模块 +| |-- cache/ # TTL + LRU 缓存 +| |-- crud/ # CRUD 模块 +| |-- file-upload/ # 文件上传模块 +| |-- health/ # 健康检查模块 +| |-- mail/ # SMTP 邮件模块 +| |-- middleware/ # HTTP 中间件集合 +| |-- pagination/ # 分页工具 +| |-- ratelimit/ # 限流算法 +| |-- rbac/ # 角色权限控制 +| `-- validation/ # 请求校验构建器 +|-- docs/ # VitePress 文档 +|-- AGENTS.md # AI 编码代理说明 +|-- CONTRIBUTING.md # 贡献指南 +`-- LICENSE # MIT +``` ## 开发 ```bash -# 克隆仓库 -git clone https://github.com/your-org/scion.git +git clone https://github.com/DarkInno/scion.git cd scion -# 运行单个模块的测试 -cd registry/auth/src/go && go test -v ./... +# registry 改动后重新生成 CLI 内置 bundle +go run ./internal/cmd/build-bundle + +# 测试和静态检查 CLI +go test ./cmd/... ./internal/... +go vet ./cmd/... ./internal/... + +# 严格检查 registry +go run ./cmd/scion doctor --strict +``` + +PowerShell 中运行所有 registry 模块测试: -# 运行所有模块的测试(PowerShell) +```powershell $modules = @('middleware','auth','crud','rbac','ratelimit','validation','file-upload','health','cache','pagination','mail') foreach ($m in $modules) { Push-Location "registry/$m/src/go"; go test ./...; Pop-Location } - -# 格式化代码 -cd registry/auth/src/go && gofmt -w . ``` -## 贡献 +## 发布 + +通过语义化版本 tag 发布: + +```bash +git tag -a v0.1.2 -m "v0.1.2" +git push origin v0.1.2 +``` -欢迎贡献!请阅读 [CONTRIBUTING.md](CONTRIBUTING.md) 了解添加新模块的指南。 +Release workflow 会验证 CLI、检查内置 bundle、交叉编译二进制、生成 `SHA256SUMS`,并发布 GitHub Release 资产。 ## 许可证 -[MIT](LICENSE) — Copyright (c) 2026 Scion Contributors +[MIT](LICENSE) diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 036083a..2fee675 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -3,7 +3,7 @@ import { defineConfig } from 'vitepress' export default defineConfig({ base: '/scion/', title: 'Scion', - description: 'Copy-paste Go backend modules — zero dependencies, security-first, AI-friendly', + description: 'Copy-paste Go backend source templates — security-first, AI-friendly', head: [ ['link', { rel: 'icon', type: 'image/svg+xml', href: '/scion/logo.svg' }] @@ -60,7 +60,7 @@ export default defineConfig({ label: '中文', lang: 'zh-CN', title: 'Scion', - description: '复制粘贴 Go 后端模块 — 零依赖、安全优先、AI友好', + description: '复制粘贴 Go 后端源码模板 — 安全优先、AI友好', themeConfig: { nav: [ { text: '指南', link: '/zh/guide/getting-started' }, diff --git a/docs/guide/getting-started.md b/docs/guide/getting-started.md index 86e6cff..dd814ed 100644 --- a/docs/guide/getting-started.md +++ b/docs/guide/getting-started.md @@ -1,32 +1,99 @@ # Getting Started -## 1. Choose a Module +## 1. Install the CLI -Browse the [Modules](/modules/) section or the `registry/` directory to find what you need. +Scion requires Go 1.22 or newer. -## 2. Copy It +```bash +go install github.com/DarkInno/scion/cmd/scion@latest +``` + +For reproducible installs, pin a release: + +```bash +go install github.com/DarkInno/scion/cmd/scion@v0.1.2 +``` + +Make sure your Go bin directory is on `PATH`, then verify the install: + +```bash +scion version +scion list +``` + +## 2. Choose a Module + +Browse the [Modules](/modules/) section or run: + +```bash +scion list +scion info cache +``` + +Modules marked `stdlibOnly=true` can be copied directly into an existing project. Modules marked `stdlibOnly=false`, such as `auth`, require `--standalone` so their `go.mod` and `go.sum` are copied explicitly. + +## 3. Copy Source Into Your Project + +Preview the files first: + +```bash +scion add cache --to internal/cache --dry-run +``` + +Copy the module: ```bash -# Example: copy the auth module -cp -r registry/auth/src/go/* yourproject/internal/auth/ +scion add cache --to internal/cache ``` -## 3. Adapt It +Scion writes `.scion-module.json` metadata in the target directory. This file records the copied module, registry version, source hashes, and whether standalone mode was used. -Each module has a `README.md` with an adaptation checklist: +## 4. Compare Later -1. **Database layer** — implement the store interface -2. **Configuration** — set environment variables -3. **Routes** — adjust prefix if needed +After you adapt the copied source, you can compare it against Scion's embedded template: -## 4. Run It +```bash +scion diff cache --target internal/cache +``` + +`diff` only reports differences. It never merges or overwrites your local changes. + +## Standalone Modules + +The `auth` module intentionally uses mature security dependencies for JWT and bcrypt. Copy it with standalone mode: + +```bash +scion add auth --standalone --to internal/auth +``` + +Scion still does not edit your project-level `go.mod`; standalone mode only copies the module's own `go.mod` and `go.sum` into the target. + +## Binary Downloads + +You can also download prebuilt binaries from [GitHub Releases](https://github.com/DarkInno/scion/releases). + +Verify downloads with `SHA256SUMS`: ```bash -# Run tests -cd yourproject/internal/auth -go test -v ./... +sha256sum -c SHA256SUMS +``` + +Windows PowerShell: + +```powershell +Get-FileHash .\scion_v0.1.2_windows_amd64.zip -Algorithm SHA256 ``` +## Manual Copy + +Manual copy still works when you are working inside the Scion repository: + +```bash +cp -r registry/cache/src/go/*.go yourproject/internal/cache/ +``` + +The CLI is preferred because it validates paths, records metadata, supports dry-runs, and enables future `scion diff` checks. + ## Available Modules | Module | Description | @@ -43,25 +110,23 @@ go test -v ./... | [Pagination](/modules/pagination) | Offset/cursor pagination | | [Mail](/modules/mail) | SMTP email with templates | -## Project Structure +## Module Structure -Each module follows this structure: +Each registry module follows this structure: -``` +```text registry// -├── src/go/ -│ ├── go.mod # module , go 1.22 -│ ├── config.go # Options struct, Defaults(), FromEnv() -│ ├── handler.go # HTTP handlers -│ ├── .go # Core logic -│ ├── _test.go # Functional tests -│ └── pentest_test.go # Penetration test cases -├── README.md # Human-readable adaptation guide -└── __llms__.md # AI-readable summary (~150 tokens) +|-- README.md # Human-readable adaptation guide +|-- __llms__.md # AI-readable summary +`-- src/go/ + |-- go.mod # module , go 1.22 + |-- config.go # Options struct, Defaults(), FromEnv() + |-- *_test.go # Functional tests + `-- pentest_test.go # Attack-scenario tests ``` ## Next Steps -- Read [Why Copy-Paste?](/guide/why-copy-paste) to understand the philosophy -- Check [Security Design](/guide/security) for security best practices -- Browse [Modules](/modules/) to find what you need +- Read [Why Copy-Paste?](/guide/why-copy-paste) to understand the philosophy. +- Check [Security Design](/guide/security) for security guarantees and constraints. +- Browse [Modules](/modules/) to find the template you need. diff --git a/docs/guide/why-copy-paste.md b/docs/guide/why-copy-paste.md index 94c29c3..c0da3f2 100644 --- a/docs/guide/why-copy-paste.md +++ b/docs/guide/why-copy-paste.md @@ -11,7 +11,7 @@ Backend modules (auth, CRUD, file upload, rate limiting) share 80% of their skel ## The Solution -Scion provides copy-paste code modules. Instead of installing a framework or pulling a dependency, you copy pre-built, production-ready modules into your project and own every line of code. +Scion provides copy-paste source modules. Instead of installing a framework or depending on Scion at runtime, you copy pre-built, production-ready modules into your project and own every line of code. ## Benefits @@ -21,7 +21,7 @@ Every line is yours after copying. No upstream lock-in. No version conflicts. No ### Explicit Dependencies -Each module uses only the Go standard library. No `go.sum` bloat. No transitive dependency vulnerabilities. +Modules use the Go standard library by default. Security-sensitive exceptions, such as JWT and bcrypt in `auth`, are declared explicitly so there are no hidden transitive dependencies. ### Security-First @@ -45,7 +45,7 @@ Every module includes functional tests and penetration test cases. Run `go test |----------|------|------| | **Package (npm/go)** | Easy to install, auto-updates | Version lock, dependency hell, hard to customize | | **Framework (Gin/Echo)** | Consistent API, community | Lock-in, bloat, learning curve | -| **Copy-paste (Scion)** | Full ownership, zero deps, customizable | Manual updates, more initial setup | +| **Copy-paste (Scion)** | Full ownership, explicit dependencies, customizable | Manual updates, more initial setup | ## When to Use Scion @@ -53,7 +53,7 @@ Every module includes functional tests and penetration test cases. Run `go test - You want to own every line of code - You need deep customization - You're building with AI coding assistants -- You want no hidden transitive dependencies +- You want standard-library defaults and no hidden transitive dependencies ## When NOT to Use Scion diff --git a/docs/zh/guide/getting-started.md b/docs/zh/guide/getting-started.md index 53bb1d5..1e8e37e 100644 --- a/docs/zh/guide/getting-started.md +++ b/docs/zh/guide/getting-started.md @@ -1,67 +1,132 @@ # 快速开始 -## 1. 选择模块 +## 1. 安装 CLI -浏览 [模块](/zh/modules/) 部分或 `registry/` 目录找到你需要的模块。 +Scion 需要 Go 1.22 或更新版本。 -## 2. 复制模块 +```bash +go install github.com/DarkInno/scion/cmd/scion@latest +``` + +如果需要固定版本: + +```bash +go install github.com/DarkInno/scion/cmd/scion@v0.1.2 +``` + +确认 Go bin 目录已加入 `PATH`,然后验证安装: + +```bash +scion version +scion list +``` + +## 2. 选择模块 + +可以浏览 [模块](/zh/modules/) 页面,也可以运行: + +```bash +scion list +scion info cache +``` + +标记为 `stdlibOnly=true` 的模块可以直接复制进现有项目。标记为 `stdlibOnly=false` 的模块,例如 `auth`,需要使用 `--standalone`,让它的 `go.mod` 和 `go.sum` 被显式复制。 + +## 3. 复制源码到项目 + +先预览将要复制的文件: + +```bash +scion add cache --to internal/cache --dry-run +``` + +执行复制: ```bash -# 示例:复制 auth 模块 -cp -r registry/auth/src/go/* yourproject/internal/auth/ +scion add cache --to internal/cache ``` -## 3. 适配模块 +Scion 会在目标目录写入 `.scion-module.json`。这个文件记录模块名、registry 版本、源文件 hash,以及是否使用 standalone 模式。 -每个模块的 `README.md` 包含适配清单: +## 4. 后续对比 -1. **数据库层** — 实现 store 接口 -2. **配置** — 设置环境变量 -3. **路由** — 根据需要调整前缀 +当你改造过复制进项目的源码后,可以和 Scion 内置模板对比: -## 4. 运行测试 +```bash +scion diff cache --target internal/cache +``` + +`diff` 只报告差异,不会自动合并,也不会覆盖你的本地改动。 + +## Standalone 模块 + +`auth` 模块为了 JWT 和 bcrypt 使用了成熟安全依赖。复制它时需要 standalone 模式: + +```bash +scion add auth --standalone --to internal/auth +``` + +Scion 仍然不会修改你的项目级 `go.mod`;standalone 模式只会把该模块自己的 `go.mod` 和 `go.sum` 复制到目标目录。 + +## 二进制下载 + +你也可以从 [GitHub Releases](https://github.com/DarkInno/scion/releases) 下载预编译二进制。 + +使用 `SHA256SUMS` 校验下载文件: ```bash -# 运行测试 -cd yourproject/internal/auth -go test -v ./... +sha256sum -c SHA256SUMS +``` + +Windows PowerShell: + +```powershell +Get-FileHash .\scion_v0.1.2_windows_amd64.zip -Algorithm SHA256 ``` +## 手动复制 + +如果你正在 Scion 仓库内部工作,仍然可以手动复制: + +```bash +cp -r registry/cache/src/go/*.go yourproject/internal/cache/ +``` + +推荐优先使用 CLI,因为它会验证路径、记录元数据、支持 dry-run,并允许之后使用 `scion diff`。 + ## 可用模块 | 模块 | 描述 | |------|------| | [Auth](/zh/modules/auth) | JWT 认证 + bcrypt | -| [CRUD](/zh/modules/crud) | 通用 CRUD + 分页 | +| [CRUD](/zh/modules/crud) | 泛型 CRUD + 分页 | | [Middleware](/zh/modules/middleware) | Recovery、CORS、日志、超时 | | [RBAC](/zh/modules/rbac) | 基于角色的访问控制 | -| [Rate Limit](/zh/modules/ratelimit) | 固定/滑动窗口、令牌桶 | -| [Validation](/zh/modules/validation) | 链式请求验证 | +| [Rate Limit](/zh/modules/ratelimit) | 固定窗口、滑动窗口、令牌桶 | +| [Validation](/zh/modules/validation) | 链式请求校验 | | [File Upload](/zh/modules/file-upload) | 安全文件上传 | | [Health](/zh/modules/health) | 存活/就绪探针 | | [Cache](/zh/modules/cache) | TTL + LRU 内存缓存 | -| [Pagination](/zh/modules/pagination) | 偏移/游标分页 | +| [Pagination](/zh/modules/pagination) | Offset/cursor 分页 | | [Mail](/zh/modules/mail) | SMTP 邮件 + 模板 | -## 项目结构 +## 模块结构 -每个模块遵循以下结构: +每个 registry 模块遵循以下结构: -``` +```text registry// -├── src/go/ -│ ├── go.mod # module , go 1.22 -│ ├── config.go # Options struct, Defaults(), FromEnv() -│ ├── handler.go # HTTP handlers -│ ├── .go # 核心逻辑 -│ ├── _test.go # 功能测试 -│ └── pentest_test.go # 渗透测试用例 -├── README.md # 人类可读的适配指南 -└── __llms__.md # AI可读的摘要 (~150 tokens) +|-- README.md # 面向人的适配指南 +|-- __llms__.md # 面向 AI 的摘要 +`-- src/go/ + |-- go.mod # module , go 1.22 + |-- config.go # Options、Defaults()、FromEnv() + |-- *_test.go # 功能测试 + `-- pentest_test.go # 攻击场景测试 ``` ## 下一步 -- 阅读 [为什么复制粘贴?](/zh/guide/why-copy-paste) 了解设计理念 -- 查看 [安全设计](/zh/guide/security) 了解安全最佳实践 -- 浏览 [模块](/zh/modules/) 找到你需要的模块 +- 阅读 [为什么复制粘贴?](/zh/guide/why-copy-paste) 了解设计理念。 +- 查看 [安全设计](/zh/guide/security) 了解安全边界和约束。 +- 浏览 [模块](/zh/modules/) 找到你需要的模板。 diff --git a/internal/version/version.go b/internal/version/version.go index 73327dd..14fd205 100644 --- a/internal/version/version.go +++ b/internal/version/version.go @@ -34,5 +34,5 @@ func CurrentCommit() string { } } } - return Commit + return "unknown" } diff --git a/internal/version/version_test.go b/internal/version/version_test.go new file mode 100644 index 0000000..f00fceb --- /dev/null +++ b/internal/version/version_test.go @@ -0,0 +1,23 @@ +package version + +import "testing" + +func TestCurrentUsesInjectedVersion(t *testing.T) { + oldVersion := Version + t.Cleanup(func() { Version = oldVersion }) + + Version = "v9.9.9" + if got := Current(); got != "v9.9.9" { + t.Fatalf("Current() = %q, want v9.9.9", got) + } +} + +func TestCurrentCommitUsesInjectedCommit(t *testing.T) { + oldCommit := Commit + t.Cleanup(func() { Commit = oldCommit }) + + Commit = "abc123" + if got := CurrentCommit(); got != "abc123" { + t.Fatalf("CurrentCommit() = %q, want abc123", got) + } +}