用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/tylerbutler/levee --skill new-endpoint命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
基于 SOC 职业分类
| name | new-endpoint |
| description | Create a new REST API endpoint with authentication |
Guide for adding a new REST endpoint to Levee.
Read lib/levee_web/router.ex to understand:
| Pipeline | Auth Level | Use For |
|---|---|---|
:api | None | Public endpoints (health check) |
:authenticated | Valid JWT | Basic auth, tenant validated |
:read_access | JWT + doc:read | Read document data |
:write_access | JWT + doc:write | Mutate document data |
:summary_access | JWT + summary:read | Read git-like storage |
:summary_write_access | JWT + summary:write | Write git-like storage |
Add the route to lib/levee_web/router.ex in the appropriate scope:
scope "/api", LeveeWeb do
pipe_through [:api, :authenticated, :read_access]
# Add your route
get "/your-path/:tenant_id/:id", YourController, :show
end
Create or update the controller in lib/levee_web/controllers/:
defmodule LeveeWeb.YourController do
use LeveeWeb, :controller
def show(conn, %{"tenant_id" => tenant_id, "id" => id}) do
# Access validated claims from auth plug
claims = conn.assigns[:claims]
# Verify tenant matches token (already done by auth plug)
# Implement your logic
case YourModule.get(tenant_id, id) do
{:ok, data} ->
json(conn, data)
{:error, :not_found} ->
conn
|> put_status(:not_found)
|> json(%{error: "not_found"})
end
end
end
Create tests in test/levee_web/controllers/:
defmodule LeveeWeb.YourControllerTest do
use LeveeWeb.ConnCase, async: true
@tenant_id "test-tenant"
@document_id "test-doc"
@user_id "test-user"
setup do
TenantSecrets.register_tenant(@tenant_id, "test-secret")
on_exit(fn -> TenantSecrets.unregister_tenant(@tenant_id) end)
:ok
end
describe "show/2" do
test "returns data with valid token", %{conn: conn} do
token = JWT.generate_test_token(@tenant_id, @document_id, @user_id)
conn =
conn
|> put_req_header("authorization", "Bearer #{token}")
|> get("/api/your-path/#{@tenant_id}/#{@document_id}")
assert json_response(conn, 200)
end
test "returns 401 without token", %{conn: conn} do
conn = get(conn, "/api/your-path/#{@tenant_id}/#{@document_id}")
assert json_response(conn, 401)
end
end
end
# Run tests
mix test test/levee_web/controllers/your_controller_test.exs
# Run all tests
just test-elixir
# Manual test with curl
TOKEN=$(mix run -e 'IO.puts Levee.Auth.JWT.generate_test_token("dev-tenant", "doc", "user")')
curl -H "Authorization: Bearer $TOKEN" http://localhost:4000/api/your-path/dev-tenant/doc
def action(conn, %{"tenant_id" => tenant_id, "id" => id, "sha" => sha}) do
def create(conn, %{"tenant_id" => tenant_id} = params) do
content = params["content"] # from JSON body
conn |> put_status(:created) |> json(data) # 201
conn |> put_status(:no_content) |> send_resp(204, "")
conn |> put_status(:bad_request) |> json(%{error: "invalid"})
The auth plug validates tenant matches token. Additional checks:
# Claims available after auth plug
claims = conn.assigns[:claims]
token_tenant = claims["tenantId"]
token_doc = claims["documentId"]