Waldur Proposal Module
The Waldur proposal module provides a comprehensive research proposal management system that enables institutions to manage competitive resource allocation through structured calls for proposals, peer review processes, and automated resource provisioning.
Architecture Overview
The proposal system follows a Call → Round → Proposal → Review → Allocation architecture that handles the complete lifecycle from call publication to resource delivery:
graph TB
subgraph "Call Management"
CMO[CallManagingOrganisation] --> C[Call]
C --> RO[RequestedOffering]
C --> CRT[CallResourceTemplate]
CD[CallDocument] --> C
end
subgraph "Submission Process"
C --> R[Round]
R --> P[Proposal]
P --> RR[RequestedResource]
P --> AR[AwardedResource]
RR --> AR
P --> PD[ProposalDocumentation]
P --> MP[Waldur Project]
end
subgraph "Review System"
P --> REV[Review]
REV --> RC[ReviewComment]
U[User/Reviewer] --> REV
end
subgraph "Resource Allocation"
P --> RA[ResourceAllocator]
AR --> MR[Marketplace Resource]
RA --> MR
PPRM[ProposalProjectRoleMapping] --> MP
end
Core Models
CallManagingOrganisation: Organizations that create and manage calls for proposalsCall: Main entity representing calls with configuration for review settings and durationRound: Time-bounded submission periods, with a lifecycle after the cut-off (evaluating → deciding → results published → closed)CallWorkflowStep: Per-call evaluation policy — which steps run and how each is gatedProposal: Individual proposals with project details and resource requestsRequestedResource: Specific resource requests within proposals linked to marketplaceAwardedResource: What the allocation decision grants; starts as a copy of the requests and is what allocation provisionsReview: Peer review system with scoring, comments, and field-specific feedback
Call Lifecycle and State Management
Call States
Calls progress through a simple but effective state machine:
stateDiagram-v2
[*] --> DRAFT : Call created
DRAFT --> ACTIVE : Call published
DRAFT --> ARCHIVED : Call canceled
ACTIVE --> ARCHIVED : Call completed
ARCHIVED --> [*]
Call State Descriptions
| State | Description | Operations Allowed |
|---|---|---|
| DRAFT | Call being prepared by organization | Edit call details, add rounds, configure offerings |
| ACTIVE | Call open for submissions | Submit proposals, manage reviews, allocate resources |
| ARCHIVED | Call completed or canceled | View historical data, generate reports |
Proposal States
Proposals follow a comprehensive lifecycle with review integration:
stateDiagram-v2
[*] --> DRAFT : Proposal created
DRAFT --> SUBMITTED : Submitter ready
DRAFT --> CANCELED : Submitter cancels
SUBMITTED --> IN_REVIEW : Review process starts
SUBMITTED --> CANCELED : Admin cancels
IN_REVIEW --> ACCEPTED : Positive review outcome
IN_REVIEW --> REJECTED : Negative review outcome
IN_REVIEW --> CANCELED : Process canceled
ACCEPTED --> [*] : Resources allocated
REJECTED --> [*] : Process complete
CANCELED --> [*] : Process terminated
A decision held for its round's publication (see
Held decisions) does not change the
state: the proposal stays IN_REVIEW with decision_held=True until the round's
results are published, and only then moves on as the decision says.
Proposal State Descriptions
| State | Description | Triggers | Actions Available |
|---|---|---|---|
| DRAFT | Proposal being prepared | User creation | Edit, add resources, upload docs |
| SUBMITTED | Proposal submitted for review | User submission | View, withdraw |
| IN_REVIEW | Under review by experts | System/admin trigger | Review, comment, score |
| ACCEPTED | Approved for resource allocation | Review completion | Allocate resources, create project |
| REJECTED | Declined after review | Review completion | View feedback, appeal |
| CANCELED | Withdrawn or administratively canceled | User/admin action | Archive |
Review States
Reviews maintain independent state for tracking progress:
stateDiagram-v2
[*] --> IN_REVIEW : Review assigned
IN_REVIEW --> SUBMITTED : Review completed
IN_REVIEW --> REJECTED : Reviewer withdraws/declines
SUBMITTED --> [*] : Review processed
REJECTED --> [*] : Assignment ended
Rounds and Evaluation Policy
What a round holds
A round is a submission window. Its scheduling fields are:
| Field | Meaning |
|---|---|
start_time |
Submissions open |
cutoff_time |
Submissions close |
review_duration_in_days |
How long an individual review may stay open before it expires |
allocation_date |
The date granted projects start when the allocation decision uses a fixed date |
A round's status (scheduled, open, ended) is derived from start_time and
cutoff_time; it is not stored. Proposals can be created and submitted only while
their round is open. After the cut-off the round has a stored lifecycle, described
in Round lifecycle after the cut-off.
When evaluation starts is the call's evaluation_start:
on_submission(default) — submitting creates the proposal's workflow step instances and activates the first enabled step at once.at_cutoff— every proposal stayssubmitteduntil its round's cut-off; an hourly task (start_evaluation_for_closed_rounds) then starts them together, so a round is evaluated as one batch. It cannot be changed while the call has proposals that are submitted or in review.
A round can be deleted only while it has no proposals at all, in any state.
Rejected and cancelled proposals are outcomes of the round and keep it; deleting
the round would delete them with it. ProtectedRoundSerializer.has_proposals
tells clients whether deletion is possible; it counts every proposal, including
those the viewer cannot see.
Where evaluation policy lives
Review and allocation policy is configured per call, on its workflow steps
(CallWorkflowStep, one row per catalogue step, seeded when the call is created):
| Setting | Meaning |
|---|---|
is_enabled |
Whether the step runs; allocation_decision is mandatory |
duration_in_days |
Step deadline, counted from when the step starts |
responsible_role |
Who acts on the step (call manager, offering manager, reviewer, panel member, applicant) |
checklist, checklist_required |
Evaluation form for the step, and whether it must be answered |
min_reviewers, min_score_threshold |
Completion gates: the step cannot be completed until enough reviews are in and their average reaches the threshold. They never decide on their own |
blind_review, requires_coi_confirmation |
Evaluator isolation and conflict-of-interest attestation |
applicant_visible |
Whether the applicant sees the step |
transition_mode |
automatic_on_completion advances to the next step when this one is completed; manual waits for a separate advance |
include_award_response, allocation_time |
On allocation_decision only: whether the applicant must accept the award, and whether allocation happens on_decision or on the round's allocation_date (fixed_date) |
The step catalogue, in order: administrative_check, technical_assessment,
expert_review, panel_review, allocation_decision, award_response.
Each step also carries notification rules (CallWorkflowStepNotificationRule):
on a trigger (step_started, step_completed, step_rejected,
step_expired, deadline_approaching) mail an audience. A rule addressed to
the applicant (or to the responsible role of a step the applicant is
responsible for) lists in notified_proposal_roles the proposal roles whose
holders are told, for example only PROPOSAL.MANAGER. Left empty, it reaches
the proposal's creator and its whole team. The applicant side gets one message
with every recipient in To; other audiences get a private copy each.
graph LR
subgraph "Round (scheduling)"
ST[Start Time] --> CT[Cutoff Time]
RD[Review Duration]
AD[Allocation Date]
end
subgraph "CallWorkflowStep (policy, per call)"
EN[Enabled / Duration] --> GT[Min Reviewers / Min Score]
GT --> TM[Transition Mode]
TM --> AT[Allocation Time:<br/>on_decision / fixed_date]
end
How long a granted project runs
When a proposal is allocated, the project's end date is decided in this order:
- The call's fixed duration (
Call.fixed_duration_in_days), whenever it is set. Prepaid subscription lengths requested under the call are capped to fit inside it, and resource end dates are clamped to the project's. - The longest awarded prepaid subscription, when the call sets no fixed
duration — measured over the proposal's
AwardedResourcerows once the award exists (see Awarded resources), and over its requests before that. - No end date, when neither applies: the project runs until someone sets one.
Round Lifecycle and Results Publication
Round lifecycle after the cut-off
Before its cut-off a round has no stored state. Once the cut-off has passed,
Round.lifecycle_state (RoundLifecycleStates) records where the round stands:
stateDiagram-v2
[*] --> evaluating : cutoff passed
evaluating --> deciding : start_deciding
evaluating --> results_published : publish_results
deciding --> results_published : publish_results
results_published --> results_published : publish_results again
results_published --> closed : complete
closed --> [*]
evaluating is entered by utils.start_round_evaluation, a conditional update
that exactly one caller wins: the hourly tasks
proposals_for_ended_rounds_should_be_cancelled and
start_evaluation_for_closed_rounds, closing a round early (close_round), and
the first lifecycle action on an ended round that the sweep has not reached yet.
The other transitions are call-manager actions in round_lifecycle.py, exposed
on ProtectedCallViewSet:
| Action | Endpoint (POST) | Transition |
|---|---|---|
| Start deciding | /api/proposal-protected-calls/{uuid}/rounds/{round_uuid}/start_deciding/ |
evaluating → deciding |
| Publish results | /api/proposal-protected-calls/{uuid}/rounds/{round_uuid}/publish_results/ |
evaluating/deciding → results_published; retries held decisions in results_published |
| Complete | /api/proposal-protected-calls/{uuid}/rounds/{round_uuid}/complete/ |
results_published → closed |
| Record adoption | /api/proposal-protected-calls/{uuid}/rounds/{round_uuid}/record_adoption/ |
No transition; any time after the cut-off |
All four take the permissions of close_round (CLOSE_ROUNDS on the call or
its managing organisation) and require an active call. Each transition records
its timestamp (evaluation_started_at, deciding_started_at,
results_published_at with results_published_by, closed_at) and emits an
event (round_evaluation_started, round_decision_started,
round_results_published, round_closed) against the managing organisation.
These fields are the round's own history: duplicating, exporting or importing a
call starts its rounds without them (Round.LIFECYCLE_FIELDS).
Publishing results and held decisions
Call.publish_results (ResultsPublication) decides when an applicant learns
the allocation decision:
immediately(default) — each decision is announced and carried out as it is made.with_round— a decision onallocation_decision(completion, rejection or expiry) is recorded on its step instance, butProposal.decision_heldis set and nothing else happens: no step notification, no state change, no award response step, no allocation.Round.withholds_resultsis true while the call iswith_roundand the round is neitherresults_publishednorclosed. The decision locks the round row, so a decision and the round's publication serialise.
publish_results releases every held decision of the round through
workflow_service.release_held_decision, as if it had just been made:
negative outcomes reject the proposal, a lapse goes where an unheld lapse goes,
an approval continues to award_response or, at the end of the workflow,
accepts and provisions. The applicant gets the notification an immediate
decision would have sent. A manual transition_mode does not park a released
decision again: publication is the call manager's confirmation.
- Undecided proposals. On a
with_roundcall, publishing is refused with400andundecided_countwhile a proposal of the round is under evaluation with neither a held nor a taken decision. Sendingforce: truewith a non-emptyreasonpublishes anyway; the reason is stored asRound.results_forced_reason, and the undecided proposals are announced as they are decided. - Partial failure. Each decision is released in its own savepoint. One that
fails (an allocation that cannot be provisioned, say) is rolled back, stays
held and is listed in
failed_proposals; publishing again retries it. - On an
immediatelycall nothing is held, so publishing only records the lifecycle.
publish_results cannot change while the call holds decisions
(Call.has_held_decisions()); switching would not release them.
Reopening. POST /api/proposal-proposals/{uuid}/reopen_decision/ with a
required reason and an optional future deadline takes a held decision back
(workflow_service.reopen_held_decision). The decision step becomes active
again with its outcome cleared, decision_held is unset, and the proposal
counts as undecided when the round publishes. Without a deadline, one that
has passed is cleared and one still ahead is kept. It is refused with 409 once
the round's results are published or when there is no held decision. Allowed
for staff and holders of UPDATE_CALL on the call or its managing organisation,
but never for the proposal's own applicant (user_can_manage_held_decision).
Nothing is sent. A proposal_decision_reopened event is filed on the
proposal's feed only, carrying the actor and the deadline but neither the
reason nor the outcome taken back; those go to the server log.
Who sees a held decision. user_can_view_held_decision: staff, support,
and holders of UPDATE_CALL on the call or its managing organisation who are
not the proposal's applicant. For everyone else:
ProposalSerializer.decision_heldandProtectedRoundSerializer.held_decisions_countarenull;- the decision step instance is serialised as still
active, without outcome, reason or completer; - the
proposal_decision_reopenedevent is hidden, through an event-type guard (logging.utils.register_event_type_guard) that applies to event listings and hook delivery alike, until the round's results are published. Evaluators never read the proposal feed at all.
held_decisions_count counts the round's held decisions; after publication it
counts only those whose release failed.
Completing a round
complete closes a results_published round. It is refused with 400 and
held_decisions_count while a decision of the round is still held (its release
failed; publish again). Proposals still without a decision follow
Round.undecided_at_completion_rule — the round's own
undecided_at_round_completion, or else the call's (UndecidedAtRoundCompletion):
refuse(default) — completing is refused with400andundecided_count.reject—workflow_service.reject_undecidedrejects each at the step it stands in, with the reason "Not decided when the round was completed." and the step's rejection notifications. A proposal parked on a completed step waiting for a manual advance is rejected on the step it was waiting to enter; one whose workflow has not started is rejected outright. Each rejection emitsproposal_rejected_at_round_completion, and the batch emitsround_undecided_proposals_rejected. The response listsrejected_proposals; a rejection that fails is listed infailed_proposals, and the round stays open until completing again rejects what is left.
Adoption record
record_adoption (multipart) stores adopted_at (required), adoption_note
and an optional adoption_document — for results that a board or another body
must adopt. While the round withholds its results, adoption_note,
adoption_document and results_forced_reason serialise as null for anyone
who may not see held decisions (user_can_view_round_adoption), and the media
endpoint applies the same rule to the document.
Resource Template System
Template Architecture
Call resource templates standardize resource requests across proposals:
graph TB
subgraph "Template Definition"
C[Call] --> CRT[CallResourceTemplate]
RO[RequestedOffering] --> CRT
CRT --> A[Attributes JSON]
CRT --> L[Limits JSON]
CRT --> REQ[Is Required]
end
subgraph "Proposal Usage"
P[Proposal] --> RR[RequestedResource]
CRT --> RR
RR --> PA[Proposal Attributes]
RR --> PL[Proposal Limits]
end
subgraph "Validation"
CRT --> V[Template Validation]
RR --> V
V --> MR[Marketplace Resource]
end
Template Configuration Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
Review System Architecture
Conflict of Interest Detection
Before assigning reviewers, the system can automatically detect potential conflicts of interest between reviewers and proposals. This ensures fair and unbiased peer review processes.
The COI detection system identifies:
- Named personnel conflicts: Reviewer appears in proposal team
- Institutional conflicts: Same or former institutional affiliation
- Co-authorship conflicts: Shared publications with proposal team
For complete documentation on COI detection, including configuration options, detection algorithms, and management workflows, see Conflict of Interest Detection.
Reviewer-Proposal Matching
The system includes an automated matching system that computes expertise affinity scores between reviewers and proposals. This ensures qualified reviewers are matched with proposals in their area of expertise.
Key features:
- Affinity scoring: Keyword-based and TF-IDF text similarity algorithms
- Reviewer discovery: Algorithm-based suggestions from published profiles
- Assignment: Greedy per proposal by stored affinity, skipping pending or recused conflicts
- Bids: Reviewers can record preferences; assignment does not use them yet
For complete documentation on the matching system, including configuration options, scoring algorithms, and API endpoints, see Reviewer-Proposal Matching.
Review Assignment
Reviewers are assigned while a proposal's expert_review step is active. The
step starts when the proposal reaches it in its workflow, which begins at
submission; the call manager then assigns reviewers manually or generates
assignment batches from the reviewer pool:
sequenceDiagram
participant P as Proposal
participant WF as Workflow steps
participant CM as Call manager
participant Rev as Reviewer
participant N as NotificationSystem
P->>WF: Submitted, first enabled step starts
WF->>WF: Earlier steps completed, expert_review starts
CM->>Rev: Assign reviewers (manual or assignment batch)
WF->>N: Notify assigned reviewers
Rev->>Rev: Complete reviews
CM->>WF: Complete step once min reviewers and min score are met
Review Scoring System
Reviews include comprehensive scoring and feedback:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
Review Visibility Configuration
Calls can configure review transparency:
| Setting | Description | Impact |
|---|---|---|
reviewer_identity_visible_to_submitters |
Whether submitters see reviewer names | False: Shows "Reviewer 1", "Reviewer 2" |
reviews_visible_to_submitters |
Whether submitters see review details | False: Only final decision visible |
Exports for Call Managers
Panel meetings, funding-body reporting and archiving work from a spreadsheet of proposals plus one document per application. Three exports cover that.
Proposal and review CSV
Two actions on the protected call stream a CSV:
| Endpoint | Rows |
|---|---|
GET /api/proposal-protected-calls/<uuid>/export-proposals/ |
One per proposal |
GET /api/proposal-protected-calls/<uuid>/export-reviews/ |
One per review |
They take the same filters as the matching lists, so a filtered table exports the rows it shows:
| Parameter | Proposals | Reviews | Limits the export to |
|---|---|---|---|
round_uuid |
✓ | ✓ | One round |
proposal_state (repeatable) |
✓ | Proposals in these states | |
review_state (repeatable) |
✓ | Reviews in these states | |
created_by_uuid |
✓ | One applicant | |
reviewer_uuid |
✓ | One reviewer | |
proposal_uuid |
✓ | One proposal | |
proposal_name |
✓ | ✓ | Proposals whose name contains the text |
The state and name filters are prefixed rather than bare state / name
because the call's own list filterset still runs when the endpoint resolves the
call, and reads a bare state or name as the call's.
An unknown state is refused with a 400 rather than ignored: a silently unfiltered file is worse than an error.
The proposal export carries the proposal's identity, its created and submitted dates, its applicant and organisation, its state and current workflow step, the science sub-domain and the requested duration, one column per requested offering component with the amount asked for, and the review counts, average score and individual scores. Rejected reviews — declined, expired or dropped for a conflict of interest — are left out of the counts, so "assigned" minus "submitted" is the number still outstanding. The column set is derived from the call, not from the proposals that matched the filters, so every row has the same shape and two exports of one call line up. An offering gets columns once it is accepted, or when proposals already asked for it before it was cancelled; a pending offering cannot carry amounts yet and is left out.
The duration is what the proposal asks for, not what was granted: reading the grant back costs a query per proposal.
Proposal.submitted_at is recorded when the proposal leaves draft. It is empty
for proposals submitted before that field existed: their submission was never
stored, and the only proxy — the first workflow step instance — was backfilled
by migration for the oldest of them, so it would read as the upgrade date. The
column is left empty rather than filled with a date that reads as fact.
The review export carries the proposal, the round, the proposal's step, the reviewer, the state, the score, the public comment and the review deadline.
Permissions and what is left out
Both exports require UPDATE_CALL on the call or its managing organisation —
staff, support (read-only) and call managers. Reviewers and panel members hold a
role on the call but not that permission, so they get a 403; an applicant cannot
see the protected call at all and gets a 404.
summary_private_commentis never exported. The review API keeps it from call managers, and the export is open to them.- Reviewer identity needs no such treatment: it is already visible to exactly
the roles that may run an export (see
ProposalReviewSerializer.get_fields), so no export can widen it. - A step's
blind_reviewdoes not apply. It hides evaluators' assessments from each other, not from the people running the call. - Text that would start a spreadsheet formula (
=,+,-,@, tab or carriage return) is written with a leading apostrophe. Proposal names, applicant profiles and review comments come from applicants and reviewers, and the file is opened by call managers. Numbers, negative ones included, are left as they are.
Scale
The response is streamed row by row, and the queryset costs a fixed number of queries regardless of how many proposals a call holds — the per-component columns are resolved once from the call, and reviews and requested resources are prefetched. A call with several thousand proposals starts sending bytes immediately instead of waiting behind a proxy's read timeout.
Per-proposal PDF
The application as the applicant filled it — fields, requested resources, team
and the names of its attachments — is rendered in the browser from the
proposal detail page (Homeport's DownloadProposalPdfAction). Rendering it
client-side keeps a PDF toolchain and its system packages out of the image for
the sake of one document, and the attachment files themselves stay behind the
media endpoint, which applies its own access rules.
Call Dashboard Statistics
GET /api/proposal-protected-calls/<uuid>/stats/ answers "where is each round?"
for one call. It returns a call block and a rounds list (one block per
round, with uuid, slug, start_time and cutoff_time). The round blocks
add up to the call block; a call with a single continuously open round has one
round block equal to the call block.
Each block holds:
| Field | Counts |
|---|---|
proposals |
Proposals by state: draft, submitted, in_review, accepted (awarded), rejected and canceled (not awarded), plus total |
admin_approved |
Proposals whose administrative check completed as eligible |
missing_admin_checks |
Proposals whose administrative check is active or expired |
reviews |
Reviews by state (in_review, submitted, rejected), plus total |
missing_reviews |
Proposals in expert review with fewer submitted reviews than the step's min_reviewers; 0 when the step sets no minimum |
overdue_reviews |
Reviews still in review past their deadline |
steps |
A list of {step, label, count}: proposals per current workflow step, over the call's enabled steps in catalogue order |
Steps disabled on the call do not appear in steps. Draft proposals have no
current step, so the step counts add up to the submitted proposals only.
The state and step counts can be opened in the proposal list: round_uuid,
state and workflow_step filter GET /api/proposal-proposals/ to the same
set.
The endpoint takes the same permission as the call's exports — staff, support (read-only), call managers and call organisers. Reviewers, panel members and managers of other calls get a 403 or 404. All counts are grouped aggregates, so the number of queries does not grow with the number of rounds or proposals.
Integration with Waldur Marketplace
Resource Provisioning Flow
Accepted proposals automatically trigger marketplace resource creation. What is
provisioned is the proposal's award (AwardedResource), not its requests:
sequenceDiagram
participant P as Proposal
participant RA as ResourceAllocator
participant MP as Marketplace
participant R as Resource
participant Proj as Project
P->>P: State changed to ACCEPTED
P->>RA: Create allocator
RA->>MP: Create marketplace order
MP->>R: Provision resources
R->>Proj: Link to proposal project
Note over Proj: Automatic role mapping
RA->>Proj: Apply ProposalProjectRoleMapping
Awarded resources
AwardedResource is what the allocation decision grants, which may differ from
the request. utils.prefill_awarded_resources copies each RequestedResource
(offering, limits, attributes, description; not the plan) when the
allocation_decision step is activated, once per proposal:
Proposal.awarded_resources_prefilled_at records it, so an award the call
manager emptied is not refilled. Allocation prefills it too if the proposal
reached allocation without one, which provisions exactly what was requested.
| Field | Meaning |
|---|---|
requested_resource |
The request the item was copied from; empty for an item the call manager added |
requested_offering |
The call offering the item is awarded on |
plan |
A plan the call manager chose; empty follows the call offering's plan at allocation (effective_plan) |
limits, attributes, description |
What is ordered |
created_by |
Who added the item |
resource |
The marketplace resource allocation provisioned |
Endpoints: GET/POST /api/proposal-proposals/{uuid}/awarded_resources/ and
GET/PATCH/PUT/DELETE /api/proposal-proposals/{uuid}/awarded_resources/{obj_uuid}/.
- Editing is for staff and users with the
CALL.MANAGERrole on the call, and only while theallocation_decisionstep is active. Otherwise the view answers409; a decision held for publication is not active, so it must be reopened first. - Validation.
requested_offering_uuidmust be an offering of the call that its provider has accepted (required when adding). The plan must belong to that offering and not be archived; moving an item to another offering without naming a plan resets it to the call offering's plan. Limits must name an amount for an offering sold by amount (names_an_amount) and pass the component bounds and precision checks an order would. Prepaid duration attributes are validated as for a request. - Approval gate. Completing
allocation_decisionwith a positive outcome is refused while an awarded item on an accepted offering names no amount. Declining is never blocked. - Allocation orders each awarded item on an accepted offering, in creation
order, on its
effective_plan, and links the resource to the item and to its request. A purchase order on the request is carried only while the item stays on the requested offering. The managers of an offering that was only awarded, never requested, see the proposal like those of a requested one.
Who reads the award (user_can_view_awarded_resources):
- staff and support, the call's managers and the managing organisation's call organisers, and managers of the offerings requested or awarded — at any time (an offering manager who is the applicant waits like an applicant);
- the applicant team (creator, proposal members, members of the granted project)
once the award is released (
awarded_resources_released): the proposal is accepted, or the decision is an approval and the award response step has started or the allocation step isapplicant_visible— never while the decision is held for the round's publication; - nobody else; reviewers and panel members judge the proposal, not the award.
Role Mapping System
The ProposalProjectRoleMapping enables automatic role assignment. A new
call starts with these mappings, which its call manager can change:
| Proposal role | Project role |
|---|---|
PROPOSAL.MANAGER |
PROJECT.MANAGER |
PROPOSAL.ADMIN |
PROJECT.ADMIN |
PROPOSAL.MEMBER |
PROJECT.MEMBER |
A duplicated or imported call takes the source's mappings instead, when they are copied.
When proposals are accepted:
- System identifies users with proposal roles
- Automatically assigns corresponding project roles
- Users gain appropriate project permissions
- Resources become accessible immediately
Order Author
When a call grants resources it places a marketplace order per granted
resource. Those orders need a name on them. It is not a formality: for an
offering fulfilled by raising a helpdesk ticket, the order's created_by is
who the request is opened on behalf of and who the service desk replies to,
and it is who Waldur addresses its own order mail to. A robot has no email
address and cannot be either.
Call.order_author decides whose name they carry:
| Value | Orders are attributed to |
|---|---|
applicant (default) |
The person who submitted the proposal |
project_manager |
The allocated project's manager |
call_manager |
A call manager on this call |
specific_user |
Call.order_author_user — e.g. a shared grants-office account |
Only someone holding a role on the call, on the organisation managing it, or on that organisation's customer may be named. Whoever is named starts receiving the call's order mail — project name, order description, limits — and, for a helpdesk-backed offering, gets an account created for them on the service desk, so the choice is kept to people already attached to the call.
1 2 3 4 | |
If the configured role is held by nobody, allocation falls back to the applicant, and then to the system robot, rather than refusing to allocate.
Being named does not grant anything
The author is a name on the order, not an authorisation.
- The spend was authorised by the call review. Accepting the proposal is
the consumer-side decision on the order: the granted project belongs to the
call's managing organisation, so whoever accepted is deciding on that
organisation's behalf, and they are recorded as the order's
consumer_reviewed_by. An automatic acceptance records the system robot. - The order is carried out with system authority. Provisioning replays the
offering plugin's own API as a user, and the person named may hold no role on
the granted project at all — a grants office typically does not. Allocated
orders are therefore processed as the system robot, and the order is flagged
placed_automaticallyto say so. - Reading a ticket in Waldur still needs a project role.
Being the order's author does not grant access to its ticket in Waldur
Helpdesk tickets raised for these orders are scoped to the allocated
project and its organization, and that scope is what decides who can read
and answer them in the customer portal. An author with no role on the
project still receives Waldur's ticket emails, but the
support/issue/<uuid>/ link in them will not open for them and they cannot
comment in Waldur — only the helpdesk side works. This is worth weighing
before pointing call_manager or specific_user at someone outside the
project, such as a grants office.
What the ticket says about people
The creation ticket for an allocated order names the order's author as its requester, and adds the applicant and a link to the proposal — they differ when the call attributes its orders to a call manager or a named contact.
The proposal team is only listed when the offering tracks team changes
(enable_issues_for_membership_changes). Such an offering normally hears about
each member through a separate membership ticket, but those are raised only
once the project holds one of its resources, and allocation adds the team
before creating any. The creation ticket therefore carries a snapshot of the
project's active members with their roles; later changes raise membership
tickets as usual. Who the team is depends on the call's
role mappings: a call with none allocates an empty project.
When the author cannot receive a ticket
A helpdesk ticket needs an address. If the order's author has none — an SSO account provisioned without an email claim, or an order left to the system robot to place — the caller falls back through the project's manager, administrator and member roles to the organization owner, taking the first active user with an address. Only when nobody on the project can be reached does the order fail, naming the project.
Because the name is on the order itself, this keeps working after allocation. When the scheduled end-date sweep or a cost policy terminates a granted resource months later, the termination order it places is attributed to the author of the resource's own creation order — the contact the call named — so its ticket reaches the same desk. The end-date sweep prefers a more specific name where there is one: whoever requested the end date, on the resource and then on the project. A candidate deactivated since is skipped. Only a creation order placed on somebody's behalf — as allocation places them — passes its name on: a resource somebody ordered themselves, an imported one, or one reconciled from a backend orphan is left to the robot and the fallback above.
Such a termination order is flagged placed_automatically and carried out with
system authority, for the same reason an allocated order is: the contact named
on it need hold no role on the project.
Realistic Usage Examples
1. Academic HPC Resource Allocation
Use Case: University research computing center allocating CPU hours
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | |
Workflow:
- Researchers submit proposals with resource requests
- Expert reviewers evaluate scientific merit
- Once three reviews averaging at least 7.0 are in, the call manager completes the review step and decides the allocation
- HPC accounts created with specified limits
- Usage tracked through marketplace billing
2. Cloud Infrastructure Grant Program
Use Case: Government agency providing cloud resources for research
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | |
Workflow:
- Research teams submit project proposals
- Panel review with domain experts
- Program managers manually select winning proposals
- Resources allocated on fixed quarterly dates
- Multi-year projects supported with renewal process
3. Startup Incubator Resource Program
Use Case: Accelerator providing development resources to startups
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | |
Workflow:
- Startups apply continuously throughout year
- Industry mentors review applications within 14 days
- Incubator staff make acceptance decisions
- Resources provisioned immediately upon acceptance
- 6-month duration with renewal option
Compliance Checklist Integration
Optional Compliance Requirements
Calls can optionally include compliance checklists that proposals must complete before submission. This feature integrates with the marketplace checklist system to ensure regulatory or institutional compliance requirements are met.
graph TB
subgraph "Compliance Flow"
C[Call] --> CC[Compliance Checklist]
CC --> P[Proposal]
P --> PCC[ProposalChecklistCompletion]
PCC --> PCA[ProposalChecklistAnswer]
PCA --> VS[Validation & Submission]
end
subgraph "Question Types"
CC --> BQ[Boolean Questions]
CC --> TQ[Text Questions]
CC --> SQ[Select Questions]
CC --> DQ[Date Questions]
end
subgraph "Review Triggers"
PCA --> RT[Review Triggers]
RT --> CMR[Call Manager Review]
CMR --> A[Approval/Comments]
end
Compliance Checklist Configuration
Call managers can assign compliance checklists when creating or editing calls:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | |
Automatic Checklist Assignment
When proposals are created for calls with compliance checklists, completion tracking is automatically initialized:
sequenceDiagram
participant U as User
participant P as Proposal
participant S as Signal Handler
participant PCC as ProposalChecklistCompletion
U->>P: Create proposal
P->>P: Save to database
P->>S: Trigger post_save signal
alt Call has compliance checklist
S->>PCC: Create completion tracking
PCC->>PCC: Initialize incomplete state
else No compliance checklist
S->>S: No action needed
end
Proposal Compliance Workflow
1. Compliance Checklist Access
Proposal managers can access compliance checklists through dedicated endpoints:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
2. Answer Submission
Proposal managers submit compliance answers:
1 2 3 4 5 6 7 8 9 10 11 | |
3. Automatic Review Triggering
Certain answers can trigger call manager review requirements:
1 2 3 4 5 6 7 8 9 10 11 | |
4. Submission Validation
Proposals cannot be submitted until compliance requirements are met:
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Call Manager Oversight
Call managers have comprehensive oversight capabilities for compliance management:
1. Compliance Overview
View compliance status across all proposals in a call:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | |
2. Detailed Answer Review
Access detailed compliance answers for specific proposals:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
3. Compliance Review and Approval
Call managers can review and approve compliance requirements:
1 2 3 4 5 6 7 8 9 10 11 12 | |
Integration with Proposal Serializers
Proposal serializers automatically include compliance status information:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | |
Real-World Use Cases
1. University Ethics Compliance
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
2. Industry Safety Compliance
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
3. Government Security Clearance
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
Benefits of Compliance Integration
- Automated Compliance Tracking: Ensures all proposals meet regulatory requirements before submission
- Flexible Question Types: Supports various question formats (boolean, text, select, date) for comprehensive compliance assessment
- Review Triggering: Automatically flags proposals requiring additional oversight based on specific answers
- Call Manager Oversight: Provides administrators with comprehensive compliance monitoring and approval capabilities
- Audit Trail: Maintains complete records of compliance answers and review decisions
- Integration with Submission: Prevents non-compliant proposals from being submitted to review process
The compliance checklist system seamlessly integrates with the existing proposal workflow while providing the flexibility needed for various regulatory and institutional requirements.
Advanced Features
Project Integration
Accepted proposals create Waldur projects with automatic configuration:
graph LR
subgraph "Proposal Acceptance"
P[Proposal ACCEPTED] --> PC[Project Creation]
PC --> RM[Role Mapping]
RM --> RA[Resource Allocation]
end
subgraph "Project Setup"
PPRM[ProposalProjectRoleMapping] --> AR[Assign Roles]
AR --> UP[User Permissions]
UP --> RS[Resource Access]
end
Notification System
Comprehensive notification system keeps stakeholders informed:
| Event | Recipients | Content |
|---|---|---|
| Proposal Submitted | Call managers, reviewers | New proposal requiring review |
| Review Assigned | Individual reviewers | Review assignment with deadline |
| Review Completed | Call managers | Review submitted notification |
| Proposal Accepted | Proposal team, call managers | Acceptance with resource details |
| Proposal Rejected | Proposal team | Rejection with feedback |
| Round Closing | All stakeholders | Deadline reminder |
Audit Trail
Complete audit logging for compliance and transparency:
1 2 3 4 5 6 7 8 9 10 | |
Error Handling and Data Integrity
Validation Framework
Comprehensive validation ensures data consistency:
1 2 3 4 5 6 7 8 9 10 | |
State Transition Guards
Prevent invalid state changes:
1 2 3 4 5 6 7 8 9 | |
Resource Cleanup
Automatic cleanup for canceled or rejected proposals:
1 2 3 4 5 6 | |
Performance Considerations
Query Optimization
- Eager loading for nested relationships
- Database indexes on frequently queried fields
- Efficient permission filtering
Scalability Patterns
- Asynchronous review assignment for large calls
- Batch processing for resource allocation
- Cached statistics for dashboard views
Monitoring Integration
- Review progress tracking
- Resource utilization monitoring
Related Documentation
- Call Eligibility and Applicant Attributes - AAI-based eligibility restrictions and GDPR-compliant attribute exposure
- Conflict of Interest Detection - COI management and detection workflows
- Reviewer Matching - Affinity scoring, reviewer suggestions and assignment
- User Profile Attributes - User attribute reference for AAI integration