You've already forked agentic-coding-workflow
feat(mcp): TokenService.IssueSystemToken (with default scope + 24h TTL)
This commit is contained in:
@@ -121,8 +121,64 @@ func (s *tokenService) IssueAdmin(ctx context.Context, in IssueAdminInput) (Issu
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IssueSystemToken 在 ACP supervisor 起 session 时调用。
|
||||||
|
//
|
||||||
|
// 重要约束:调用必须在已经创建 acp_sessions row 的事务**之后或同一事务内**进行 ——
|
||||||
|
// 因为 mcp_tokens.acp_session_id 是 NOT NULL CHECK + FK,session row 不存在则
|
||||||
|
// FK 校验失败。spec §6.1 明确建议同事务提交。本 service 不直接管事务边界(由
|
||||||
|
// ACP SessionService 在 Create 流程内编排),但调用顺序由调用方保证。
|
||||||
|
//
|
||||||
|
// 默认 ExpiresIn = 24h;默认 Tools 为内置 PM 工具白名单(spec §6.2)。
|
||||||
|
// 写一条 audit `mcp.token.create_system`。
|
||||||
func (s *tokenService) IssueSystemToken(ctx context.Context, in IssueSystemTokenInput) (IssueResult, error) {
|
func (s *tokenService) IssueSystemToken(ctx context.Context, in IssueSystemTokenInput) (IssueResult, error) {
|
||||||
panic("not implemented: IssueSystemToken")
|
if in.ExpiresIn <= 0 {
|
||||||
|
in.ExpiresIn = 24 * time.Hour
|
||||||
|
}
|
||||||
|
tools := in.Tools
|
||||||
|
if tools == nil {
|
||||||
|
// 用 copy 避免共享 defaultSystemTools 给调用方修改
|
||||||
|
tools = append([]string{}, defaultSystemTools...)
|
||||||
|
}
|
||||||
|
expires := time.Now().Add(in.ExpiresIn)
|
||||||
|
|
||||||
|
plain, hash, err := NewToken()
|
||||||
|
if err != nil {
|
||||||
|
return IssueResult{}, errs.Wrap(err, errs.CodeInternal, "generate system token")
|
||||||
|
}
|
||||||
|
|
||||||
|
id := uuid.New()
|
||||||
|
created, err := s.repo.Create(ctx, &MCPToken{
|
||||||
|
ID: id,
|
||||||
|
TokenHash: hash,
|
||||||
|
UserID: in.UserID,
|
||||||
|
Name: "acp:" + in.ACPSessionID.String(),
|
||||||
|
Issuer: IssuerSystem,
|
||||||
|
Scope: Scope{Tools: tools, ProjectIDs: in.ProjectIDs},
|
||||||
|
ACPSessionID: &in.ACPSessionID,
|
||||||
|
ExpiresAt: &expires,
|
||||||
|
CreatedBy: in.UserID, // system 签发时 created_by 即 owner(无 admin 操作者)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return IssueResult{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = s.audit.Record(ctx, audit.Entry{
|
||||||
|
UserID: &in.UserID,
|
||||||
|
Action: "mcp.token.create_system",
|
||||||
|
TargetType: "mcp_token",
|
||||||
|
TargetID: created.ID.String(),
|
||||||
|
Metadata: map[string]any{
|
||||||
|
"token_id": created.ID.String(),
|
||||||
|
"acp_session_id": in.ACPSessionID.String(),
|
||||||
|
"user_id": in.UserID.String(),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return IssueResult{
|
||||||
|
ID: created.ID,
|
||||||
|
Plaintext: plain,
|
||||||
|
ExpiresAt: created.ExpiresAt,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
func (s *tokenService) Authenticate(ctx context.Context, plaintext string) (*MCPToken, error) {
|
func (s *tokenService) Authenticate(ctx context.Context, plaintext string) (*MCPToken, error) {
|
||||||
panic("not implemented: Authenticate")
|
panic("not implemented: Authenticate")
|
||||||
|
|||||||
Reference in New Issue
Block a user