Skip to content

duly_task.source carries the same catalog-default bug as duly_duty.source, and a member can hand-create a duly_task #55

Description

@os-warren

Found while implementing #50 (flip duly_duty.source's default to self), whose
file surface was src/objects/duty.object.ts only. Filed rather than fixed —
src/objects/task.object.ts is a different object with its own claim risk,
and the PM adjudication comment on #50 scoped only the duty object.

What

duly_task.source (src/objects/task.object.ts) declares the identical
three-option select, with the identical comment calling it the caliber field
metrics are allowed to read — and the identical default: true sitting on
catalog:

source: Field.select({
  label: 'Source',
  required: true,
  options: [
    { label: 'Role catalog', value: 'catalog', color: '#16515F', default: true },
    { label: 'Assigned by manager', value: 'assigned', color: '#8C6512' },
    { label: 'Self-declared', value: 'self', color: '#576B73' },
  ],
}),

Unlike the assignment fan-out (which writes duly_task.source explicitly —
see below), the dispatcher (src/jobs/dispatch.plan.ts:382,
source: duty.source ?? '') also always writes it explicitly, copied from the
parent duty. So the dispatched-task path is not exposed.

But src/security/permission-sets.ts grants the duly_member position
duly_task: { allowCreate: true, allowRead: true, allowEdit: true, readScope: 'own', writeScope: 'own' } — a member can create their own duly_task
directly, not just via dispatch. src/views/task.view.ts puts source on
several columns/tooltips but defines no create form that stamps it, so a
hand-created task falls back to the field default: catalog. That is the
same inversion #50 just fixed on the duty side — a self-declared task would be
born into the governed, scoreable set.

Why filed separately rather than fixed alongside #50

Correction to #50's stated premise, surfaced along the way

#50 and its adjudication comment describe "the assignment fan-out" as a
producer of a governed duty with source: 'assigned'. It isn't: the
fan-out (src/flows/assignment.flow.ts) never creates a duly_duty row at
all — both its create_record nodes target objectName: 'duly_task'
directly. It writes source: 'assigned' on the task, unconditionally,
so it is unaffected by either this finding or #50. Doesn't change either
fix; noted because the premise as stated is imprecise and this is the
object where it actually applies.

Suggested acceptance sketch

  • a hand-created duly_task with no source supplied is self
  • the dispatcher still produces catalog/assigned (copied from the duty) —
    already covered by test/dispatch.test.ts / test/dispatch-wiring.test.ts
  • the assignment fan-out still produces assigned — already covered by
    test/assignment-fanout.test.ts
  • an invariant test pins the direction, next to the one A hand-created duty defaults to source: 'catalog', so a self-declared duty is born scoreable #50 added in
    test/invariants.test.ts

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions