refactor(mcp): apply Part 1 review I1+I3+I4+I5

- Rename MCPToken -> Token (mcp.Token reads cleaner; zero external callers yet)
- IssueSystemToken: guard against nil ACPSessionID / UserID (early input validation)
- TokenService: inject now func for clock injection (parity with RateLimiter)
- Repository CHECK constraint tests: assert wrapped CodeInternal

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-08 10:28:49 +08:00
parent 980c6fcf0e
commit a00f5a9efd
7 changed files with 106 additions and 65 deletions
+16 -11
View File
@@ -62,7 +62,7 @@ func TestPgRepo_AdminToken_CRUD(t *testing.T) {
require.NoError(t, err)
expires := time.Now().Add(90 * 24 * time.Hour)
created, err := repo.Create(ctx, &mcp.MCPToken{
created, err := repo.Create(ctx, &mcp.Token{
ID: uuid.New(),
TokenHash: hash,
UserID: uid,
@@ -133,12 +133,14 @@ func TestPgRepo_CheckConstraint_SystemRequiresSession(t *testing.T) {
require.NoError(t, err)
// system token + 没 acp_session_id → CHECK 拒绝
_, err = repo.Create(ctx, &mcp.MCPToken{
_, err = repo.Create(ctx, &mcp.Token{
ID: uuid.New(), TokenHash: hash, UserID: uid,
Name: "x", Issuer: mcp.IssuerSystem, CreatedBy: uid,
})
require.Error(t, err)
// PG 抛 23514 check_violation;包装在 errs.CodeInternal 里
ae, ok := errs.As(err)
require.True(t, ok)
assert.Equal(t, errs.CodeInternal, ae.Code, "CHECK violation should wrap to CodeInternal")
}
func TestPgRepo_CheckConstraint_AdminMustNotHaveSession(t *testing.T) {
@@ -152,12 +154,15 @@ func TestPgRepo_CheckConstraint_AdminMustNotHaveSession(t *testing.T) {
fakeSessionID := uuid.New()
// admin token + 有 acp_session_id → CHECK 拒绝
_, err = repo.Create(ctx, &mcp.MCPToken{
_, err = repo.Create(ctx, &mcp.Token{
ID: uuid.New(), TokenHash: hash, UserID: uid,
Name: "y", Issuer: mcp.IssuerAdmin, ACPSessionID: &fakeSessionID,
CreatedBy: uid,
})
require.Error(t, err)
ae, ok := errs.As(err)
require.True(t, ok)
assert.Equal(t, errs.CodeInternal, ae.Code, "CHECK violation should wrap to CodeInternal")
}
func TestPgRepo_List_FilterByCaller(t *testing.T) {
@@ -171,7 +176,7 @@ func TestPgRepo_List_FilterByCaller(t *testing.T) {
mkAdmin := func(uid uuid.UUID, name string) {
_, hash, _ := mcp.NewToken()
_, err := repo.Create(ctx, &mcp.MCPToken{
_, err := repo.Create(ctx, &mcp.Token{
ID: uuid.New(), TokenHash: hash, UserID: uid, Name: name,
Issuer: mcp.IssuerAdmin, CreatedBy: admin,
})
@@ -208,7 +213,7 @@ func TestPgRepo_List_ActiveOnly(t *testing.T) {
expPast := time.Now().Add(-1 * time.Hour)
mk := func(name string, exp *time.Time) uuid.UUID {
_, hash, _ := mcp.NewToken()
tok, err := repo.Create(ctx, &mcp.MCPToken{
tok, err := repo.Create(ctx, &mcp.Token{
ID: uuid.New(), TokenHash: hash, UserID: user, Name: name,
Issuer: mcp.IssuerAdmin, ExpiresAt: exp, CreatedBy: admin,
})
@@ -245,7 +250,7 @@ func TestPgRepo_PurgeExpired(t *testing.T) {
// 一个早已过期的 row(手工写 expires_at = 30d ago)
_, hash, _ := mcp.NewToken()
tk, err := repo.Create(ctx, &mcp.MCPToken{
tk, err := repo.Create(ctx, &mcp.Token{
ID: uuid.New(), TokenHash: hash, UserID: user, Name: "old",
Issuer: mcp.IssuerAdmin, ExpiresAt: &old, CreatedBy: admin,
})
@@ -253,7 +258,7 @@ func TestPgRepo_PurgeExpired(t *testing.T) {
// 一个新 token
_, hash2, _ := mcp.NewToken()
_, err = repo.Create(ctx, &mcp.MCPToken{
_, err = repo.Create(ctx, &mcp.Token{
ID: uuid.New(), TokenHash: hash2, UserID: user, Name: "new",
Issuer: mcp.IssuerAdmin, ExpiresAt: &expFuture, CreatedBy: admin,
})
@@ -323,7 +328,7 @@ func TestPgRepo_RevokeBySession(t *testing.T) {
// 插一个 system token
_, hash, _ := mcp.NewToken()
tk, err := repo.Create(ctx, &mcp.MCPToken{
tk, err := repo.Create(ctx, &mcp.Token{
ID: uuid.New(), TokenHash: hash, UserID: uid,
Name: "system-x", Issuer: mcp.IssuerSystem,
Scope: mcp.Scope{ProjectIDs: []uuid.UUID{pid}},
@@ -359,7 +364,7 @@ func TestPgRepo_ReapStaleSystemTokens(t *testing.T) {
// 一个 crashed session 的 system token
sidCrashed, pidA := mustInsertACPSetup(t, ctx, pool, uid, "crashed")
_, h1, _ := mcp.NewToken()
tk1, err := repo.Create(ctx, &mcp.MCPToken{
tk1, err := repo.Create(ctx, &mcp.Token{
ID: uuid.New(), TokenHash: h1, UserID: uid,
Name: "crashed-tok", Issuer: mcp.IssuerSystem,
Scope: mcp.Scope{ProjectIDs: []uuid.UUID{pidA}},
@@ -370,7 +375,7 @@ func TestPgRepo_ReapStaleSystemTokens(t *testing.T) {
// 一个 running session 的 system token(不该被 reap)
sidRunning, pidB := mustInsertACPSetup(t, ctx, pool, uid, "running")
_, h2, _ := mcp.NewToken()
tk2, err := repo.Create(ctx, &mcp.MCPToken{
tk2, err := repo.Create(ctx, &mcp.Token{
ID: uuid.New(), TokenHash: h2, UserID: uid,
Name: "running-tok", Issuer: mcp.IssuerSystem,
Scope: mcp.Scope{ProjectIDs: []uuid.UUID{pidB}},