Skip to main content
Wildo.ai Coming soon

Authorization and isolation

Link records to eligible people and partners

A referenced person or organization can exist without being eligible for this record. Wildo can require the declared membership or partnership before accepting the link.

An Acme task can reference a member, while its attempted reference to an outsider is refused.

Link records to eligible people and partners

A referenced person or organization can exist without being eligible for this record. Wildo can require the declared membership or partnership before accepting the link.

That keeps relationships meaningful: an assignee belongs to the account, an escalation contact belongs to its rota, or a partner belongs to an approved relationship.

Example — Assign work to an account member

A task can refer to a user only when that user has the required membership in the task’s organization. Knowing somebody’s user ID is not enough.

For engineers

This is the task-assignee declaration in Wonder Todos. scopeMembership: true asks the registry to resolve the organization-membership junction. The context settings separately control the related information returned with the task:

This implementation excerpt from tasks-manager.relationships.ts shows the decision in context; explanatory source comments are omitted.

createResourcesRelationship(
    TasksManager_ResourceType.TODOS, CoreResourceType.USERS,
    ResourceRelationshipCardinality.MANY, ResourceRelationshipCardinality.ONE,
    {
      nature: RelationshipNature.REFERENCE,
      foreignKeyField: 'assignedToUserId', // Explicit for Edge Case #1 - multiple FKs to same type
      parentResourceRequirement: ResourceParentResourceRequirement.OPTIONAL,
      accessScopeStrategy: ResourceRelationshipAccessScopeStrategy.OPTIONAL_CONTEXT,
      scopeMembership: true,
      contextPolicy: {
        objectMode: ContextPolicy_ObjectMode.SUMMARY,
        operationOverrides: {
          [CoreResourceOperation.READ]: { objectMode: ContextPolicy_ObjectMode.FULL },
          [CoreResourceOperation.LIST]: { enabled: false },
          [CoreResourceOperation.SEARCH]: { enabled: false },
        }
      }
    }
  ),

Use an explicit junction when membership means something else

For a rota or partnership, set scopeMembership to an object naming the junction. junctionScopeField and junctionTargetField identify its columns when they cannot be inferred. The target’s existence and the junction’s existence answer different questions; both matter.

Create and update integrity checks evaluate referenced foreign keys before storing the write. An operation can add referenceConstraints to tighten eligibility, such as requiring a particular membership status. Related-record resolution uses the declared membership semantics as well.

Separate who may assign from who may be assigned

Wonder Todos’ assign-lead operation uses the same assignedToUserId relationship shown above and declares an active organization administrator as its eligible target. The caller must also be an administrator. The example below uses built-in organization roles: permission to make the change does not make every selected person eligible.

This is the operation declaration from todos.resources-config.ts, with comments omitted. Todos_Operations belongs to the application; the other enums come from @wildo-ai/saas-models, and z comes from zod.

[Todos_Operations.ASSIGN_LEAD]: {
  variants: [
    {
      variantType: ResourceOperationVariantType.API_CALL,
      isDefault: true,
      roles: [CORE_ORG_ROLES.ORG_ADMIN],
      riskLevel: ResourceOperationRiskLevel.MEDIUM,
      resourceOperationLike: CoreResourceOperation.UPDATE,
      requestDto: z.object({
        assignedToUserId: z.string().min(1),
      }),
      referenceConstraints: {
        assignedToUserId: {
          qualifyingStatuses: [OrganizationMemberStatus.ACTIVE],
          requiredRoles: { scope: ResourcePrimaryScope.ORGANIZATIONS, roles: [CORE_ORG_ROLES.ORG_ADMIN] },
        },
      },
    },
  ],
},

Place this inside the resource’s operationsConfiguration. The shared tasks-manager module contributes its factory map through resourceConfigurations and its relationship list through resourceRelationships. Both are needed: the relationship identifies the membership junction; this operation adds the eligibility criteria. Merely adding an input field does not declare that relationship.

For an existing todo, call the addressed operation with the organization’s administrator session. API_BASE includes the backend API prefix; ASSIGNEE_USER_ID is the selected user’s ID, not their membership ID.

curl --fail-with-body --request PUT "$API_BASE/organizations/$ORGANIZATION_ID/todos/$TODO_ID/assign-lead" \
  --header "Authorization: Bearer $ADMIN_ACCESS_TOKEN" \
  --header 'Content-Type: application/json' \
  --data "{\"assignedToUserId\":\"$ASSIGNEE_USER_ID\"}"
Selected person using built-in rolesResult with an authorized caller
Active administrator in this organizationEligible; verify the stored assignedToUserId after the update
Active owner in this organizationEligible through role inheritance: owner includes administrator authority
Member holding only ORG_MEMBER in this organizationRefused by this operation’s role requirement on the target
Administrator belonging only to another organizationRefused: the required membership is in the todo’s organization
Membership outside the qualifying statusRefused even if the membership carries an administrator role

Run the permitted case before testing refusals, and confirm refused writes leave the previous assignee unchanged. The ordinary assign operation on this resource does not add these status/role criteria: it retains the relationship’s membership check. If several operations must enforce the stricter policy, declare it on each applicable variant.

Target roles are resolved against the application’s current role definitions in the declared scope. A custom role can qualify through its inheritance; an unknown role grants nothing. Related-record search can offer members who do not meet a stricter write policy, so handle an assignment refusal even when the person appeared in a picker.

Make exceptions deliberate

This policy is opt-in on the relationship. An organization-less target without it may receive an existence check rather than a membership check. A variant that explicitly waives membership changes the contract for that variant; do not use that escape hatch to make an ordinary assignment work around an incomplete declaration.

Building a B2B product or an internal tool?

Wildo is not self-service yet. Tell us what you have in mind and we will say plainly whether it fits, and what happens next.