# 手動快速開始

Source: https://gortexa.sheng.page/quickstart/

這份快速開始會裝好 pinned 工具鏈、建立專案、從 proto 產生一組 CRUD API，並驗證三個協定都通——在已有 Go 1.21+ 的機器上大約十分鐘。

## 安裝

安裝開發工具鏈（buf、protoc plugins、sqlc、govulncheck，版本全部 pinned）：

```bash
GORTEXA_VERSION="v0.28.3" # 只在驗證過較新 release 後才更新
export GORTEXA_REF="$GORTEXA_VERSION"
export GOTOOLCHAIN=auto
/bin/bash -c "$(curl -fsSL "https://raw.githubusercontent.com/yshengliao/gortexa/$GORTEXA_VERSION/install.sh")"
go install github.com/yshengliao/gortexa/cmd/gortexa@"$GORTEXA_VERSION"
```

在 checkout 之外執行時，腳本會把 repo clone 到 `./gortexa`（用 `GORTEXA_DIR` 改位置，裝完可刪）；只在偵測到壞掉的 container Go 設定時才寫入全域 `go env`，一般機器的 Go 設定不會被動到。

注意：v0.28.0 與 v0.28.1 的 `go.mod` 帶有 `replace` 指令，`go install …@` 這兩個版本會被 Go 拒絕（「contains one or more replace directives」）。CLI 請釘 v0.28.2 以上；v0.27.5 也能裝，但它產生的 scaffold 沒有本頁描述的 namespace 與 api 模組行為。

`go install` 把執行檔放在 `$(go env GOPATH)/bin`，多數 shell 的 PATH 預設不含這個目錄——沒加的話下一步會直接 `command not found: gortexa`：

```bash
export PATH="$(go env GOPATH)/bin:$PATH"    # 建議加進 shell profile
```

裝完可以用 `gortexa doctor` 檢查 Go toolchain 與 proto 工具是否就緒。

CLI 全部指令一覽：`create`（建專案）、`gen`（產生 API）、`regen`（proto 變更後重新生成）、`run`（啟動 dev server）、`export --format mcp|openai|gemini [--out file]`（匯出 AI tool schema）、`tools install`（安裝 pinned 工具鏈）、`tools sync`（重釘某個工具版本）、`skills install`／`skills list`（AI 助理技能）、`doctor`（環境檢查）、`version`。

## 建立專案

```bash
gortexa create myapp --module github.com/me/myapp \
  --repo https://github.com/yshengliao/gortexa.git --ref v0.28.3
cd myapp
# create 不會寫入可用 secret，只留下會拒絕啟動的 placeholder；確認它在。
grep -Fq 'jwt_secret: "dev-only-insecure-secret-change-me-please"' etc/config.yaml
```

`create` 會複製框架佈局、改寫 module path、丟棄 git 歷史。產出的專案自帶一個 sample resource、完整攔截器鏈、config、health 與 MCP bridge。sample 放在專案自己的 proto namespace：package `myapp.resource.v1`，位於 `proto/myapp/resource/v1/`。namespace 從 module path 最後一段推出，記錄在 `.gortexa/project.json`，`gortexa doctor` 會印出這份 manifest。

**這是可執行 demo，不是資料服務**
接下來的 gen 會產生 process-local in-memory logic；重啟會遺失資料，多 replica 不會共享狀態。請把它當作 contract／transport 骨架，正式服務必須接上持久化、authorization 與真實 readiness。若你已在 framework checkout 完成工具鏈安裝，請在新 project 用 gortexa doctor 驗證，不要假設 make bootstrap 可在 scaffold 內重裝工具鏈。

## 產生第一個 API

```bash
gortexa gen billing/v1 Invoice
```

這個指令產生 proto contract（含 validation 與 AI annotations）、in-memory logic stub 與 server wiring，並跑完 buf lint → breaking → generate。服務落在專案的 namespace 下：package `myapp.billing.v1`，檔案 `proto/myapp/billing/v1/invoice.proto`，MCP 與 gRPC 看到的服務名是 `myapp.billing.v1.InvoiceService`。之後改 proto 就跑 `gortexa regen`。覆寫既有 API 要加 `--force`——注意它同時隱含 `--allow-breaking`，會跳過 buf 的 breaking-change 閘門。

`gen/` 下全是產生碼：不手動編輯，只由 `make gen` 產生（照框架慣例進版控，複製來的 CI 有 drift 防護閘）。

## 啟動與驗證

以下是單一 shell 的 smoke test：它用短期 runtime secret、保留 `gortexa run` 的相同 server entrypoint、等待服務就緒，並註冊 binary 與 log 的 cleanup。server 會暫留給下一段 token 流程；請不要在這些命令之間更換 shell。

```bash
export GORTEXA_AUTH__JWT_SECRET="$(openssl rand -hex 32)"
go build -o ./.gortexa-prototype-server ./cmd/server
./.gortexa-prototype-server >./gortexa-prototype.log 2>&1 &
SERVER_PID=$!
cleanup() { kill -TERM "$SERVER_PID" 2>/dev/null || true; wait "$SERVER_PID" 2>/dev/null || true; rm -f ./.gortexa-prototype-server ./gortexa-prototype.log; }
trap cleanup EXIT INT TERM
(
  set -euo pipefail
  for _ in $(seq 1 60); do
    if curl -fsS http://127.0.0.1:8080/healthz >/dev/null 2>&1; then break; fi
    sleep 0.5
  done
  curl -fsS http://127.0.0.1:8080/healthz
  test "$(curl -sS -o /dev/null -w '%{http_code}' http://127.0.0.1:8080/v1/resources/x)" = 401
  curl -fsS -X POST http://127.0.0.1:8080/mcp \
    -H 'Content-Type: application/json' \
    -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
)
```

HTTP gateway 的最後一發回 401 是預期行為；它與 gRPC、MCP 共用 authentication。這個 smoke test 不代替 live gRPC E2E 或 authorization 測試。若只需要 smoke test、不會繼續下一段，現在執行 `cleanup; trap - EXIT INT TERM` 即可停止 server 並清除暫存檔。若要一般互動式開發，可在同一個已 export secret 的 shell 直接執行 `gortexa run`，再以 Ctrl-C 停止。

## 取得開發用 token

伺服器仍在上一步的同一個 shell 中執行。先確認暫時 command 尚不存在，再建立它的資料夾：

```bash
test ! -e cmd/devtoken
mkdir -p cmd/devtoken
```

建立一個暫時 command（它不含 secret），把下列程式存為 `cmd/devtoken/main.go`；若 module 不是 `github.com/me/myapp`，替換 import：

```go
package main

import (
	"fmt"
	"os"
	"time"

	"github.com/me/myapp/auth"
)

func main() {
	secret := os.Getenv("GORTEXA_AUTH__JWT_SECRET")
	v, err := auth.NewVerifier([]byte(secret), "gortexa")
	if err != nil {
		panic(err)
	}
	tok, err := v.Sign("dev", []string{"admin"}, time.Hour)
	if err != nil {
		panic(err)
	}
	fmt.Println(tok)
}
```

執行它、驗證 authenticated request，然後移除暫時 command 並停止 server：

```bash
TOKEN="$(go run ./cmd/devtoken)"
AUTH_STATUS="$(curl -sS -o /dev/null -w '%{http_code}' http://127.0.0.1:8080/v1/resources/x -H "Authorization: Bearer $TOKEN")"
test "$AUTH_STATUS" = 200 || test "$AUTH_STATUS" = 404
printf 'authenticated HTTP status=%s\n' "$AUTH_STATUS"
rm cmd/devtoken/main.go
rmdir cmd/devtoken
cleanup
trap - EXIT INT TERM
```

不要把 real secret 從 `etc/config.yaml` 複製、提交或打進 image。正式環境請改由 secret manager、mounted file 或 runtime environment 注入並輪替。

## 以模組使用（不走 scaffold）

框架的所有 package 都可以直接 `go get` 單獨引用，不必建立 scaffold 專案：

```bash
go get github.com/yshengliao/gortexa@latest
```

最小 app（一個 h2c port、gRPC health、`/healthz`、`/readyz`）完全不需要 codegen。`kernel.New` 要求你明確決定治理鏈：傳 `WithInterceptors` 掛上八段鏈，或傳 `WithoutInterceptors()` 明示不要——兩者都不給會在啟動時直接失敗，框架不讓你用「忘記寫」的方式做這個決定。下面示範第二種，而它之所以安全，只因為它除了 health 什麼都不服務；註冊真正的 service 前請改用 `WithInterceptors`：

```go
package main

import (
	"context"
	"log"
	"os/signal"
	"syscall"

	"github.com/yshengliao/gortexa/health"
	"github.com/yshengliao/gortexa/kernel"
)

func main() {
	ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
	defer stop()

	// 預設：h2c :8080、graceful shutdown。WithoutInterceptors 是刻意的 opt-out：
	// 沒有 recover、auth、rate limit 與 validation。
	app, err := kernel.New(kernel.WithoutInterceptors())
	if err != nil {
		log.Fatal(err)
	}
	app.Health().Register("self", func(context.Context) health.State { return health.Healthy })

	if err := app.Run(ctx); err != nil {
		log.Fatal(err)
	}
}
```

由此往上疊，AI 與非 AI 路徑都是一等公民：

- 非 AI 服務：`config` 分層設定、`interceptor` 治理鏈、`httpcompat` gateway mux、`apperr` 三協定錯誤模型，加上 `mq`／`cache`／`storage`／`client`。
- AI 服務：proto 標上 `gortexa/ai/v1/annotations.proto`（Go bindings 在配套模組 `github.com/yshengliao/gortexa/api`，import 路徑 `github.com/yshengliao/gortexa/api/gen/gortexa/ai/v1`，`go get` 框架時會一併解析），以 `mcp.NewBridge` 把標注的 RPC 變成走同一條攔截器鏈的 MCP tools。

每個公開元件的用途、import 路徑與最小範例，見[元件用法](https://gortexa.sheng.page/components/)。

注意：自 v0.28.0 起，`gortexa create` 產出的專案可以再 `go get` 框架：`gortexa.ai.v1` 的 descriptor 只由專案與框架共同依賴的 `github.com/yshengliao/gortexa/api` 模組註冊一次，sample 也在專案自己的 namespace，不會相撞。但專案本身已內含一份框架原始碼（改寫成自己的 module path），再 import `github.com/yshengliao/gortexa/...` 等於同時連進兩份獨立的框架程式碼，只在需要自己那份沒有的東西時才這麼做。v0.27 及更早的 scaffold 沒有這個保證：兩份 copy 都會註冊 `gortexa/ai/v1/annotations.proto`，binary 會在 init 時 panic。

## 在框架 checkout 內開發

直接開發框架本身時用 make：

```bash
make bootstrap          # 安裝 pinned 工具鏈
make gen                # buf lint → breaking → generate
make test               # go test -race
make run                # 啟動範例伺服器（注入本機開發用 JWT secret）
make dev                # docker compose 起 Jaeger、Grafana、Prometheus
```

## 下一步

- [核心概念](https://gortexa.sheng.page/concepts/)：單一 port 多工、攔截器鏈、錯誤模型怎麼運作。
- [設定](https://gortexa.sheng.page/configuration/)：config.yaml 全欄位與環境變數覆寫。
- [範例索引](https://gortexa.sheng.page/examples/)：11 個可執行的驗證範例。
