feat(mcp): IssueSystemTokenWithTx for cross-module tx (spec §6.1)

- Extract issueSystemToken helper; pool-bound + tx-bound entries share impl
- IssueSystemTokenWithTx accepts pgx.Tx, uses repo.WithTx(tx) for DB writes
- Audit Record stays outside tx (audit failure doesn't roll back business path)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-08 12:44:37 +08:00
parent 33057e885f
commit 3a448cee5f
2 changed files with 36 additions and 7 deletions
+21
View File
@@ -385,3 +385,24 @@ func TestIssueSystemToken_NilUserID(t *testing.T) {
// 编译期保证:类型实现接口
var _ = errors.New
func TestIssueSystemTokenWithTx_DelegatesToRepoWithTx(t *testing.T) {
t.Parallel()
repo := newFakeRepo()
au := &fakeAudit{}
svc := mcp.NewTokenService(repo, au, nil)
uid := uuid.New()
sid := uuid.New()
pid := uuid.New()
res, err := svc.IssueSystemTokenWithTx(context.Background(), nil, mcp.IssueSystemTokenInput{
UserID: uid, ACPSessionID: sid, ProjectIDs: []uuid.UUID{pid},
})
require.NoError(t, err)
assert.NotEmpty(t, res.Plaintext)
assert.Equal(t, []string{"mcp.token.create_system"}, au.actions())
got, err := repo.GetByID(context.Background(), res.ID)
require.NoError(t, err)
assert.Equal(t, mcp.IssuerSystem, got.Issuer)
}