Feat v0.3.4 team roles + multi-party validation (#18)
Custom team roles: removed CHECK constraint on team_members.role, roles stored in teams.settings, roles API, stage_config.required_role enforced on claim. Multi-party signoff: workflow_signoffs table, validation gate in advanceInternal, SubmitSignoff engine method, signoff HTTP API. Frontend: dynamic role management, stage config validation UI, signoff panel. Design docs for extension lifecycle and trigger composition. 20 store tests passing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -660,6 +660,48 @@ func (s *WorkflowStore) ListAssignmentsByUser(ctx context.Context, userID string
|
||||
return s.queryAssignments(ctx, q, args...)
|
||||
}
|
||||
|
||||
// ── Signoffs (v0.3.4) ─────────────────────────
|
||||
|
||||
func (s *WorkflowStore) CreateSignoff(ctx context.Context, so *models.WorkflowSignoff) error {
|
||||
return DB.QueryRowContext(ctx, `
|
||||
INSERT INTO workflow_signoffs (instance_id, stage, user_id, decision, comment)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING id, created_at`,
|
||||
so.InstanceID, so.Stage, so.UserID, so.Decision, so.Comment,
|
||||
).Scan(&so.ID, &so.CreatedAt)
|
||||
}
|
||||
|
||||
func (s *WorkflowStore) ListSignoffs(ctx context.Context, instanceID, stage string) ([]models.WorkflowSignoff, error) {
|
||||
rows, err := DB.QueryContext(ctx, `
|
||||
SELECT id, instance_id, stage, user_id, decision, comment, created_at
|
||||
FROM workflow_signoffs
|
||||
WHERE instance_id = $1 AND stage = $2
|
||||
ORDER BY created_at`, instanceID, stage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var result []models.WorkflowSignoff
|
||||
for rows.Next() {
|
||||
var so models.WorkflowSignoff
|
||||
if err := rows.Scan(&so.ID, &so.InstanceID, &so.Stage, &so.UserID,
|
||||
&so.Decision, &so.Comment, &so.CreatedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result = append(result, so)
|
||||
}
|
||||
return result, rows.Err()
|
||||
}
|
||||
|
||||
func (s *WorkflowStore) CountSignoffs(ctx context.Context, instanceID, stage, decision string) (int, error) {
|
||||
var count int
|
||||
err := DB.QueryRowContext(ctx, `
|
||||
SELECT COUNT(*) FROM workflow_signoffs
|
||||
WHERE instance_id = $1 AND stage = $2 AND decision = $3`,
|
||||
instanceID, stage, decision).Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
func (s *WorkflowStore) queryAssignments(ctx context.Context, q string, args ...interface{}) ([]models.WorkflowAssignment, error) {
|
||||
rows, err := DB.QueryContext(ctx, q, args...)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user