Feat v0.3.3 public entry background jobs (#17)
Co-authored-by: Jeffrey Smith <jasafpro@gmail.com> Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
This commit was merged in pull request #17.
This commit is contained in:
@@ -239,6 +239,68 @@ func (e *Engine) Cancel(ctx context.Context, instanceID string, userID string) e
|
||||
return nil
|
||||
}
|
||||
|
||||
// ── Public Entry (v0.3.3) ───────────────────
|
||||
|
||||
// StartPublic creates an instance for a public_link workflow without authentication.
|
||||
// The caller is identified as "public:<uuid>". Returns the instance including its entry_token.
|
||||
func (e *Engine) StartPublic(ctx context.Context, workflowID string, initialData json.RawMessage) (*models.WorkflowInstance, error) {
|
||||
wf, err := e.stores.Workflows.GetByID(ctx, workflowID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("workflow not found: %w", err)
|
||||
}
|
||||
if wf.EntryMode != "public_link" {
|
||||
return nil, fmt.Errorf("workflow %q does not accept public entry", wf.Name)
|
||||
}
|
||||
anonymousID := "public:" + uuid.New().String()
|
||||
return e.Start(ctx, workflowID, initialData, anonymousID)
|
||||
}
|
||||
|
||||
// ResumePublic returns an active instance by its entry token. No authentication required.
|
||||
func (e *Engine) ResumePublic(ctx context.Context, entryToken string) (*models.WorkflowInstance, error) {
|
||||
inst, err := e.stores.Workflows.GetInstanceByToken(ctx, entryToken)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("instance not found: %w", err)
|
||||
}
|
||||
if inst.Status != models.InstanceStatusActive {
|
||||
return nil, fmt.Errorf("instance is %s, not active", inst.Status)
|
||||
}
|
||||
return inst, nil
|
||||
}
|
||||
|
||||
// AdvancePublic advances an instance identified by entry token. Only public-audience stages
|
||||
// can be advanced this way. The original anonymous identity is used as the actor.
|
||||
func (e *Engine) AdvancePublic(ctx context.Context, entryToken string, stageData json.RawMessage) (*models.WorkflowInstance, error) {
|
||||
inst, err := e.stores.Workflows.GetInstanceByToken(ctx, entryToken)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("instance not found: %w", err)
|
||||
}
|
||||
if inst.Status != models.InstanceStatusActive {
|
||||
return nil, fmt.Errorf("instance is %s, not active", inst.Status)
|
||||
}
|
||||
|
||||
// Load version snapshot to check audience
|
||||
ver, err := e.stores.Workflows.GetVersion(ctx, inst.WorkflowID, inst.WorkflowVersion)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("version not found: %w", err)
|
||||
}
|
||||
var stages []models.WorkflowStage
|
||||
if err := json.Unmarshal(ver.Snapshot, &stages); err != nil {
|
||||
return nil, fmt.Errorf("corrupt snapshot: %w", err)
|
||||
}
|
||||
|
||||
// Find current stage and validate audience
|
||||
for _, s := range stages {
|
||||
if s.Name == inst.CurrentStage {
|
||||
if s.Audience != models.AudiencePublic {
|
||||
return nil, fmt.Errorf("stage %q requires authenticated access", s.Name)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return e.advanceInternal(ctx, inst.ID, stageData, inst.StartedBy, 0)
|
||||
}
|
||||
|
||||
// emit publishes an event on the bus.
|
||||
func (e *Engine) emit(_ context.Context, label, room string, payload map[string]any) {
|
||||
if e.bus == nil {
|
||||
|
||||
Reference in New Issue
Block a user