01Operations · Business workflow

Build an equipment-request app around your company's rules.

Give employees one place to request equipment, reviewers a clear approval step, and Operations a record of delivery. Keep improving the workflow as your company's rules change.

CanLang builds the app
Records, permissions, workflows and connected screens.
Soda OS runs the factory
AI development, persistent Projects and reviewed changes.

Illustrative application and company rules. CanLang also works independently of Soda OS.

View CanLangBack to app
EquipmentRequests.canExcerpt

Approval and recorded delivery

When
 crud Equipment by=coordinator fields=name,category,active delete=none
 crud Request by=members fields=equipment,reason when=row.requested_by==actor and row.status==requested delete=none
 # Review another teammate's request against the equipment catalogue.
 scenario approve(request:Request) by=reviewer
  require request.status==requested and request.requested_by!=actor
  require request.equipment.active
  do set request {status=approved,approved_by=actor,approved_at=now}
 # Record the physical asset when approved equipment reaches the requester.
 scenario deliver(request:Request,asset_tag:text) by=coordinator
  require request.status==approved and trim(asset_tag)!=""
  do set request {status=delivered,asset_tag=trim(asset_tag),delivered_at=now}

Equipment · App preview

Equipment
EQ-1042 · Avery

Standing desk

Approved
Alex approved14 Oct · details locked
Asset tag · 15 OctDESK-001
Delivered

Illustrative application interface · sample records.

02CanLang · Application model

People, records and rules.

Your department decides how the work should run. This example expresses those decisions in CanLang: the records it stores, who can access them, and the rules each action must follow.

Records the CanLang app keeps

Illustrative first-version records and relationships
Catalogue item → RequestStanding desk
Requester
Avery
Required detail
Business reason
  1. AveryRequests equipmentFollows their own request
  2. Alex · ReviewerApproves Avery’s requestDifferent from the requester
  3. OperationsRecords deliveryAsset tag: DESK-001

A catalogue item and a request connect the equipment, business reason, requester and status. Approval records its actor and time; delivery records its time and asset tag.

First-version workflow

  1. Requested
  2. Approved
  3. Delivered

People and app access

Employee
Create and read their own requests; edit while awaiting approval.
Reviewer
Read the queue and approve another person's request for active catalogue equipment.
Operations coordinator
Maintain the catalogue, read the queue and record delivery.

What these permissions mean

Expected behavior · illustrative cases, not executed test results

Allowed
Alex approves Avery’s eligible request once.
Refused
Avery approves Avery’s own request.
CanLang · Explicit business rules

What the app protects

The department sets these requirements. The CanLang application expresses the permissions and workflow restrictions.

  1. Self-approval and repeated approval are refused.

  2. After approval, the equipment selection, reason and requester cannot be rewritten.

  3. Delivery requires approval and a nonempty asset tag.

  4. Completed delivery details remain protected.

These are application permissions and business rules. Soda OS and Forgejo govern the separate development and code-review process in section 04.

See how these records and responsibilities connect
Illustrative workflow · Operations
From the catalogueStanding desk
Requester
Avery
Includes
Business reason
  1. 01
    Avery requestsOnly their own requests
  2. 02
    Alex approvesDifferent from the requester
  3. 03
    Operations records deliveryApproval first. Asset tag required.

Approved details stay protected.

Read this app’s CanLang source
03CanLang · Application experience

Use the app. Check the result.

Follow the first-version workflow through its screens, then check that the app allows the right actions and protects the right records.

A walkthrough of the first version

  1. Avery requests

    Avery follows their own request. An unrelated ordinary employee cannot read it.

  2. Alex approves

    Alex differs from Avery. Holding the reviewer role would not allow Alex to approve their own request.

  3. Operations records delivery

    The coordinator records the asset tag after approval. The completed handover remains read-only.

View CanLangBack to app
EquipmentRequests.canExcerpt

Approval and recorded delivery

When
 crud Equipment by=coordinator fields=name,category,active delete=none
 crud Request by=members fields=equipment,reason when=row.requested_by==actor and row.status==requested delete=none
 # Review another teammate's request against the equipment catalogue.
 scenario approve(request:Request) by=reviewer
  require request.status==requested and request.requested_by!=actor
  require request.equipment.active
  do set request {status=approved,approved_by=actor,approved_at=now}
 # Record the physical asset when approved equipment reaches the requester.
 scenario deliver(request:Request,asset_tag:text) by=coordinator
  require request.status==approved and trim(asset_tag)!=""
  do set request {status=delivered,asset_tag=trim(asset_tag),delivered_at=now}

Illustrative first-version application

Equipment
WorkspaceRequests Internal app
Equipment register

Requests & delivery

1 delivery recorded
EQ-1042 · Catalogue

Standing desk

Avery Active item

Alex approved · 14 Oct, 10:24Equipment, reason and requester locked
Delivery recordDESK-001Asset tag · 15 Oct, 09:10
Delivered
View request history
  1. Avery requested a standing desk14 Oct, 09:05 · equipment and business reason recorded
  2. Alex approved the request14 Oct, 10:24 · approved details protected
  3. Operations recorded delivery15 Oct, 09:10 · asset tag DESK-001 · completed handover protected

Illustrative application interface. The linked CanLang browser demo has the smaller scope described below.

Your department · Acceptance checklist

Does this version do the job?

Use these expected outcomes to accept the CanLang app. Try the relevant roles, including actions that must be refused.

Checks to perform on the illustrative first version; these are not reported test results.

Equipment requests · First version

Expected outcomes

  1. Avery can create and follow a request; an unrelated employee cannot read it.

  2. An authorised reviewer can approve another person's eligible request, once.

  3. Approved selection, reason and requester stay protected.

  4. Delivery is refused before approval or without an asset tag.

  5. Recorded delivery updates the status and protects the completed details.

Reference: the sample records behind these checks

Avery requests

Equipment
Standing desk
Requester
Avery
Status
Requested

Alex approves

Reviewer
Alex
Decision
Approval recorded
Status
Approved

Operations records delivery

Handover
Delivery recorded
Asset tag
DESK-001 · illustrative
Status
Delivered

Try a focused CanLang demo

The compact browser demo covers request and approval. The larger first-version source adds catalogue and delivery. The Finance continuation is a separate application version; the compact demo does not demonstrate it.

Try the approval example in CanLang
04Soda OS · Software factory

Develop and review the app.

Your department defines the result. Soda OS coordinates authorised coding agents in a persistent Project; Forgejo records the work and applies the review and merge policy.

Start from the business request

“We need employees to request equipment from our catalogue. A reviewer must approve someone else's request before Operations records delivery. Employees should see their own requests, and approved details should stay protected.”

Follow the development process

Move through the stages below: accepted direction, dependent work items, CanLang source, independent review and policy-governed integration.

Corrections and human approval apply where required by repository policy. Merging code and deploying the application are separate actions.

The request, work items and review cases are illustrative, not a recording of a completed factory run.

1 / 6 · Operations owns the direction

Agree on equipment, approval and delivery.

Operations opens New Project and answers “What do you want to build?” Explore ideas develops the experience. In “Review your product direction”, Operations accepts the rules or asks for changes before implementation.

What carries forward

An accepted application direction, with people, records and refusal cases. Material questions return to Operations.

Illustrative accepted direction

Illustrative accepted direction

Avery requests a standing desk

  1. One catalogue and a personal request list

    Employees choose equipment, explain the business reason and follow their own requests. Reviewers and Operations can read the queue.

  2. Another person approves

    A reviewer approves another person’s eligible request for active equipment. Self-approval and a second approval are refused.

  3. Operations records delivery

    A coordinator records delivery only after approval, with a nonempty asset tag. Approved request details and completed delivery records stay protected.

Illustrative workflow artifact from the selected department journey.

2 / 6 · Soda coordinates the work

Give the workflow a plan with prerequisites.

Operations authorizes a finite planning allowance and chooses a repository. Soda creates native Forgejo work items with acceptance criteria and explicit dependencies. Execution needs repository authorization, accounts and capacity.

What carries forward

Accepted work-item criteria and prerequisite outcomes. Unresolved dependencies and unanswered requirements keep work from advancing.

Illustrative native work items

Illustrative native work items

From catalogue to an accountable handover

  1. Define equipment, requests and access

    Store catalogue availability, request ownership and status. Employees read their own requests; reviewers and coordinators read the queue.

  2. Implement guarded approval and delivery

    Depends on records and permissions. Check the reviewer’s identity and request state; require approval and an asset tag before delivery.

  3. Connect screens and check outcomes

    Depends on the allowed operations. Test Avery’s request, Alex’s approval and the coordinator’s delivery, alongside unrelated-reader and self-approval refusals.

Illustrative workflow artifact from the selected department journey.

3 / 6 · The coding agent implements

Build the agreed request-to-delivery rules.

Soda assesses readiness and prepares the persistent Project and assigned checkout. The coding agent implements the accepted work with repository context and authorized access, then reports a candidate and evidence. Soda OS publishes the pull request.

What carries forward

A candidate pull request at an exact revision. Spaces shows agent activity and intervention needs alongside Forgejo.

EquipmentRequests.can · first-version source excerpt

Catalogue, separate approval and delivery

Given
 role reviewer
 role coordinator
 Equipment {
  name:text trim max=120 label="Equipment",
  category:enum(computer,furniture,accessory) label="Category",
  active:bool=true label="Available to request"
 }
 Request {
  equipment:Equipment label="Equipment",
  reason:text trim max=500 label="Business reason",
  requested_by:user server=actor label="Requested by",
  status:enum(requested,approved,delivered)=requested label="Status",
  approved_by:user? label="Approved by",
  approved_at:datetime? label="Approved at",
  delivered_at:datetime? label="Delivered at",
  asset_tag:text? label="Asset tag"
 }
 policy Equipment read=members
 policy Request read=members where=row.requested_by==actor
 policy Request read=reviewer
 policy Request read=coordinator
 invariant Request: trim(row.reason)!=""
 lock Request fields=equipment,reason,requested_by when=row.status!=requested
 lock Request fields=approved_by,approved_at when=row.status!=requested
 lock Request fields=status,delivered_at,asset_tag when=row.status==delivered
When
 crud Equipment by=coordinator fields=name,category,active delete=none
 crud Request by=members fields=equipment,reason when=row.requested_by==actor and row.status==requested delete=none
 # Review another teammate's request against the equipment catalogue.
 scenario approve(request:Request) by=reviewer
  require request.status==requested and request.requested_by!=actor
  require request.equipment.active
  do set request {status=approved,approved_by=actor,approved_at=now}
 # Record the physical asset when approved equipment reaches the requester.
 scenario deliver(request:Request,asset_tag:text) by=coordinator
  require request.status==approved and trim(asset_tag)!=""
  do set request {status=delivered,asset_tag=trim(asset_tag),delivered_at=now}
4 / 6 · Another agent checks the candidate

Check identity as well as the reviewer role.

A separate agent session reviews the exact candidate alongside required checks. Findings return to the coding role; revised candidates receive fresh checks, with further independent review when evidence or repository policy requires it.

What carries forward

Evidence belongs to the revised candidate. These are illustrative review expectations, rather than a report of a completed factory run.

Illustrative review and correction

Illustrative review and correction

A reviewer must not approve their own request

  1. Finding: a role check would allow self-approval

    If Avery also held the reviewer role, checking that role alone would permit Avery to approve the standing desk request.

  2. Correction: check identity, state and availability

    Require an awaiting request from another person and active catalogue equipment. Delivery separately requires approval and a valid asset tag.

  3. Fresh review: exercise permitted and refused paths

    Alex can approve Avery’s request; Avery cannot approve it. Refuse repeated approval, delivery before approval and changes to approved or delivered details. An unrelated employee cannot read Avery’s request.

Illustrative workflow artifact from the selected department journey.

5 / 6 · Forgejo policy governs integration

Integrate when current evidence satisfies policy.

Soda merges when required checks and review pass for the exact candidate and repository policy permits it. Required human approval is part of that path. Changed or missing evidence prevents integration.

What carries forward

Confirmed integration lets Soda reassess dependent work. Application deployment remains a separate action.

Integration conditions

Integration conditions

The revision, evidence and native outcome agree

  1. The candidate still matches

    The pull request’s current revision is the revision that was checked and reviewed.

  2. Required evidence is current

    Checks, review and any required human approval satisfy the repository’s policy.

  3. Forgejo confirms integration

    The native merge and work-item outcome are recorded before dependent work is reassessed.

Illustrative workflow artifact from the selected department journey.

6 / 6 · Operations and employees assess the result

Follow Avery’s request through the handover.

Employees and Operations assess the agreed workflow: Avery requests a standing desk, Alex approves it and a coordinator records delivery. The larger CanLang source covers that first version. The compact browser example lets you try request and approval rules.

What carries forward

A workflow assessed against the department’s acceptance outcomes. The next agreed improvement enters the same persistent Project.

Try the equipment approval example
View CanLangBack to app
EquipmentRequests.canExcerpt

Approval and recorded delivery

When
 crud Equipment by=coordinator fields=name,category,active delete=none
 crud Request by=members fields=equipment,reason when=row.requested_by==actor and row.status==requested delete=none
 # Review another teammate's request against the equipment catalogue.
 scenario approve(request:Request) by=reviewer
  require request.status==requested and request.requested_by!=actor
  require request.equipment.active
  do set request {status=approved,approved_by=actor,approved_at=now}
 # Record the physical asset when approved equipment reaches the requester.
 scenario deliver(request:Request,asset_tag:text) by=coordinator
  require request.status==approved and trim(asset_tag)!=""
  do set request {status=delivered,asset_tag=trim(asset_tag),delivered_at=now}

Equipment · App preview

Equipment
EQ-1042 · Avery

Standing desk

Approved
Alex approved14 Oct · details locked
Asset tag · 15 OctDESK-001
Delivered

Illustrative application interface · sample records.

Read the application outcomes

Requested → Approved → Delivered

  • Avery follows a personal request

    Choose catalogue equipment and explain the reason. Ordinary employees cannot read another person’s requests.

  • Alex approves; Operations records delivery

    Approval protects the request details. A nonempty asset tag records the handover, with completed delivery fields preserved.

  • The next requirement stays with this app

    Operations can later add Finance approval above €1,000 through a separately reviewed change. That continuation has its own supporting source; it does not extend the compact demo.

Read the factory handbook
Where this walkthrough comes from

The factory sequence and interface names follow the product documents and source code. Application behavior follows the matching complete examples on the CanLang page.

05CanLang app · Continued in the Soda OS factory

Add Finance approval above €1,000.

The business changes its requirements. Revise the CanLang app in the same persistent Project, use the factory to develop and review the change, and check what must keep working.

What changes in the application

Illustrative new requests · Two paths

€1,000 or less

  1. Reviewer
  2. Delivery

Exactly €1,000 uses this path.

Above €1,000

  1. Reviewer
  2. Finance
  3. Delivery

Finance approval is required before delivery.

Earlier requests keep their original workflow.

Initial rule
A separate reviewer approves the request before Operations records delivery.
New rule
For new requests above €1,000, ordinary approval leads to Awaiting Finance. A separate Finance approval is required before delivery. Exactly €1,000 follows the ordinary path.
What stays protected
The requester, initial approver and Finance approver are different people. Reviewed amounts and decisions stay fixed. Earlier requests, including pending ones, keep their original workflow and records.

The revised app experience

View CanLangBack to app
EquipmentRequestsFinance.canRule-change excerpt

Independent Finance approval above €1,000

When
 crud Equipment by=coordinator fields=name,category,active delete=none
 crud Request by=members fields=equipment,reason,amount when=row.requested_by==actor and row.status==requested delete=none
 # Review another teammate's request against the equipment catalogue.
 scenario approve(request:Request) by=reviewer
  require request.status==requested and request.requested_by!=actor
  require request.equipment.active
  do
   if request.policy==finance_threshold and request.amount!=null and request.amount.minor>100000
    set request {status=awaiting_finance,approved_by=actor,approved_at=now}
   else
    set request {status=approved,approved_by=actor,approved_at=now}
  examples request=pending
   as,request.amount,request.policy -> request.status
   first_reviewer,money(450,"EUR"),finance_threshold -> approved
   first_reviewer,money(1000,"EUR"),finance_threshold -> approved
   first_reviewer,money(1400,"EUR"),finance_threshold -> awaiting_finance
   first_reviewer,money(1400,"EUR"),original -> approved
   first_reviewer,null,original -> approved
   members,money(450,"EUR"),finance_threshold -> error(forbidden)
  examples request=pending
   as,request.requested_by,request.status -> request.status
   first_reviewer,first_reviewer,requested -> error(rule_failed)
   first_reviewer,claimant,approved -> error(rule_failed)
 # Finance must be a third person, even when one person has multiple roles.
 scenario approve_finance(request:Request) by=finance
  require request.status==awaiting_finance and request.policy==finance_threshold
  require request.requested_by!=actor and request.approved_by!=actor
  do set request {status=approved,finance_by=actor,finance_at=now}
  examples request=pending
   as,request.status,request.amount,request.approved_by -> request.status,request.finance_by
   finance_reviewer,awaiting_finance,money(1400,"EUR"),first_reviewer -> approved,finance_reviewer
   first_reviewer,awaiting_finance,money(1400,"EUR"),first_reviewer -> error(rule_failed)
   claimant,awaiting_finance,money(1400,"EUR"),first_reviewer -> error(rule_failed)
   finance_reviewer,approved,money(1400,"EUR"),first_reviewer -> error(rule_failed)
 # Record the physical asset when approved equipment reaches the requester.
 scenario deliver(request:Request,asset_tag:text) by=coordinator
  require request.status==approved and trim(asset_tag)!=""
  do set request {status=delivered,asset_tag=trim(asset_tag),delivered_at=now}
  examples request=pending
   as,request.status,asset_tag -> request.status,request.asset_tag
   coordinator,approved,"DESK-104" -> delivered,"DESK-104"
   coordinator,awaiting_finance,"DESK-104" -> error(rule_failed)
   coordinator,approved," " -> error(rule_failed)
   members,approved,"DESK-104" -> error(forbidden)
   coordinator,delivered,"DESK-104" -> error(rule_failed)
Illustrative CanLang rule-change excerpt · open the complete revised source for records, permissions and interfaces.Read the complete source

Equipment · After a rule change

Equipment
WorkspaceRequests Internal app
Equipment register

Finance review

1 awaiting Finance
EQ-1048 · Catalogue

Standing desk

Avery Active item

Approval policy
Finance review above €1,000
Alex approved · 14 Oct, 10:24€1,400 · amount locked after review
Awaiting FinanceMorgan · Finance

Decision not yet recorded. Morgan is different from Avery and Alex.

Delivery blockedFinance approval required before handover.
Review history & delivery requirements
  1. Avery requested a standing desk14 Oct, 09:05 · equipment and business reason recorded
  2. Alex approved €1,40014 Oct, 10:24 · approved details protected
  3. Finance review pendingNo Finance decision or delivery recorded. A nonempty asset tag is required after approval.
Policy applied to this request
€1,000 or less
Independent reviewer approval, then delivery.
Above €1,000
Reviewer approval, then a third person in Finance, then delivery.
Earlier requests
Earlier requests retain their original policy, including while pending. Their records and decisions remain unchanged.

Requester, reviewer and Finance approver must be different people. A recorded decision cannot be repeated.

Illustrative application interface · sample records.

Read the full rule, protections and review checks
Illustrative company policy · new requests

One amount. Two approval paths.

EmployeeRequest equipmentPositive total in EUR
Ordinary reviewerApprove another person's requestReviewed amount is now locked
€450 or exactly €1,000€1,000 or less
Ordinary approval is enough
For example, €1,400Above €1,000
Awaiting FinanceA third person approves

Delivery refused until Finance approves.

Operations records deliveryRequired approvals + nonempty asset tag

Earlier requests keep their original route. Pending and completed requests retain their previous workflow, records and decisions. Each request shows which policy applies.

Requester, initial approver and Finance approver must be three different people—even when one person holds multiple roles. Repeated decisions are refused.

  • Record a positive total in EUR. Ordinary approval locks the reviewed amount.
  • At €450 or exactly €1,000: reviewer → delivery. At €1,400: reviewer → Finance → delivery.
  • Finance can read requests requiring its approval. Its approver differs from both requester and initial approver, even when one person holds multiple roles.
  • While Finance approval is missing, delivery is refused. Repeated decisions are refused.
  • Apply the policy only to requests created after it takes effect. Show which policy applies on each request; preserve all earlier records and decisions.
Read the revised CanLang source and version coverage
06Your company · Requirements and next steps

Make the rules your own.

Use this example to agree a first useful workflow with its owner and technical counterpart. Identity, purchasing, inventory and other connections need their own evaluation.

Catalogue
Which equipment and availability rules belong in the first version?
Approvers
Who may review, and when is a distinct Finance decision required?
Visibility
Who may see a request and its delivery evidence?
Delivery evidence
What confirms handover for each kind of equipment?
Currency and amounts
Choose currency, thresholds and rounding rules for your company.
Existing work
Agree what happens to existing requests before accepting a changed rule.

Explore another workflow · Read the factory handbook · Get help