Rules-as-code · Plain-English guide
How the digitised rules work out which licences and permits an activity in a Victorian State forest needs, and what the application must contain. Written for a non-technical reader.
This ruleset asks one question: “which licences or permits does this application need?” The applicant describes what they intend to do in a State forest, and for each intended activity the rules switch on a matching requirement.
The core pattern
Each regulated activity has a trigger. If the applicant's answers match it, the rules mark the matching Permit required.
One extra idea · lists
Where an applicant lists several extra activities, the rules apply the same checks to each item in the list.
One extra idea · must-do
Beyond permitted/forbidden, a rule can mark something Obligated — a step the applicant must complete (here, stating a purpose once any permit is triggered).
You provide a fact · Rules work out a conclusion.
An individual or a business, with an address and contact details.
Yes/no intentions that drive every permit decision, plus supporting detail (area flags, equipment, cattle, written authorities).
Each switched on when its trigger is met.
Seven independent checks each look at what the applicant intends and, if it matches, switch on the matching requirement. They don't interact — an application can trigger any number.
| If the applicant intends to… | …when this is true | Then this is |
|---|---|---|
| Leave gates open or damage a gate | Either is “yes” | Gate permit required |
| Fell a survey-marked tree / deface a survey mark | Either is “yes” | Tree-felling licence required |
| Enter a restricted area | Area is experimental, nursery, plantation or fenced — and known to be prohibited | Restricted-area permit required |
| Interfere with research equipment | Equipment is for experimentation and used in research | Research permit required |
| Sell goods or services | “yes” | Permit to sell required |
| Enter reserved forest with cattle | “yes” | Cattle-entry permit required |
| Cut, dig or take away forest produce | “yes” | Take-away permit required |
Two triggers are compound — more than one condition must line up:
One final rule ties the checks together. If the application has triggered a licence or permit, stating a purpose becomes Obligated — the applicant must do it. (The check ORs eight of the nine requirement flags together; one — taking away forest produce — is left out, and a never-set grazing flag is left in. See Observations.)
Mandatory applicant details: title, given name and family name, plus the address's street number, street name, suburb, state and postcode are Required; the unit number is Optional.
Additional activities are handled with a “for each” check: for every extra activity the applicant lists, the permitted act and the person or class it applies to are required, and an additional-activity request is recorded (which in turn obliges a purpose).
Coverage at a glance
9 test suite(s), 22 scenario(s), 21 expectation(s) in total. 21 scenario(s) assert an outcome; 1 assert nothing (inputs only).
Scenarios that assert nothing exercise the rules but cannot pass or fail — they are a coverage gap worth noting.
Coverage here is genuinely assertive: 21 of the 22 scenarios check an outcome, and the suites are organised one-per-permit. Every permit-required flag carries both a positive case (trigger present → permit required) and a negative one (trigger absent → not required) — exactly the shape you want — and the two compound triggers are tested on both sides: the restricted-area suite pairs a “known experimental area” (required) with an “unknown experimental area” (not required), and the research suite separates “for experimentation” from “used in research”.
Since the previous review, two scenarios that asserted nothing now assert a value: 8 Applications → Information not required… now checks that isPurposeSpecified comes out False when no permit fires, and the (7) Additional activities scenario now asserts isAdditionalActivityRequested is True. The gaps worth closing: (1) the purpose obligation is still untested — no scenario asserts the Obligated modality on isPurposeSpecified; (2) the remaining assert-nothing scenario, 8 Applications → Data required for licence, leaves the applicant name/address requirements unverified; (3) the grazing-licence flag is never asserted, consistent with no rule setting it (see Observations); (4) the additional-activities suite has only a positive case — and, confusingly, the scenario is named “No additional activities…” yet supplies one activity and asserts the request flag True (there is no genuine empty-list case); and (5) no scenario triggers several permits at once, so the independence of the checks is untested. The restricted-area suite also omits the nursery and fenced branches.
Given these inputs
| @id: | F6lsPSSQB3C68tf4g4LN4YqB |
| @type: | Regsoft |
| @name: | debug-hang-repro |
| application.damageGate: | False |
| application.leaveGatesOpen: | False |
| application.activity.damageGate: | False |
| application.activity.leaveGatesOpen: | False |
Then expect
Given these inputs
| @id: | F6lsPSSQB3C68tf4g4LN4YqB |
| @type: | Regsoft |
| @name: | debug-hang-repro |
| application.damageGate: | False |
| application.leaveGatesOpen: | True |
| application.activity.damageGate: | False |
| application.activity.leaveGatesOpen: | True |
Then expect
Given these inputs
| @id: | F6lsPSSQB3C68tf4g4LN4YqB |
| @type: | Regsoft |
| @name: | debug-hang-repro |
| application.damageGate: | True |
| application.leaveGatesOpen: | False |
| application.activity.damageGate: | False |
| application.activity.leaveGatesOpen: | True |
Then expect
Given these inputs
| @id: | k8ssAjfvJqd1bhQq8NTYcNcI |
| @type: | Regsoft |
| @name: | Not asking to feel does not receive a licence |
| application.defaceInscribedSurveyMark: | False |
| application.fellTreeBearingInscribedSurveyMark: | False |
| application.activity.defaceInscribedSurveyMark: | False |
| application.activity.fellTreeBearingInscribedSurveyMark: | False |
Then expect
Given these inputs
| @id: | k8ssAjfvJqd1bhQq8NTYcNcI |
| @type: | Regsoft |
| @name: | Not asking to feel does not receive a licence |
| application.defaceInscribedSurveyMark: | True |
| application.fellTreeBearingInscribedSurveyMark: | False |
| application.activity.defaceInscribedSurveyMark: | True |
| application.activity.fellTreeBearingInscribedSurveyMark: | False |
Then expect
Given these inputs
| @id: | k8ssAjfvJqd1bhQq8NTYcNcI |
| @type: | Regsoft |
| @name: | Not asking to feel does not receive a licence |
| application.defaceInscribedSurveyMark: | False |
| application.fellTreeBearingInscribedSurveyMark: | True |
| application.activity.defaceInscribedSurveyMark: | False |
| application.activity.fellTreeBearingInscribedSurveyMark: | True |
Then expect
Given these inputs
| @id: | qny2geqQe4pNOp7YeGvvl5Wl |
| @type: | Regsoft |
| @name: | Not entering restricted area = no permit required |
| application.forestArea.areaIsFenced: | False |
| application.forestArea.isExperimentalArea: | False |
| application.forestArea.isPlantation: | False |
| application.forestArea.isTreeNursery: | False |
| application.forestArea.knownToBeProhibited: | False |
| application.activity.enterArea.areaIsFenced: | False |
| application.activity.enterArea.isExperimentalArea: | False |
| application.activity.enterArea.isPlantation: | False |
| application.activity.enterArea.isTreeNursery: | False |
| application.activity.enterArea.knownToBeProhibited: | False |
Then expect
Given these inputs
| @id: | qny2geqQe4pNOp7YeGvvl5Wl |
| @type: | Regsoft |
| @name: | Not entering restricted area = no permit required |
| application.forestArea.areaIsFenced: | False |
| application.forestArea.isExperimentalArea: | True |
| application.forestArea.isPlantation: | False |
| application.forestArea.isTreeNursery: | False |
| application.forestArea.knownToBeProhibited: | True |
| application.activity.enterArea.areaIsFenced: | False |
| application.activity.enterArea.isExperimentalArea: | True |
| application.activity.enterArea.isPlantation: | False |
| application.activity.enterArea.isTreeNursery: | False |
| application.activity.enterArea.knownToBeProhibited: | True |
Then expect
Given these inputs
| @id: | qny2geqQe4pNOp7YeGvvl5Wl |
| @type: | Regsoft |
| @name: | Not entering restricted area = no permit required |
| application.forestArea.areaIsFenced: | False |
| application.forestArea.isExperimentalArea: | False |
| application.forestArea.isPlantation: | True |
| application.forestArea.isTreeNursery: | False |
| application.forestArea.knownToBeProhibited: | True |
| application.activity.enterArea.areaIsFenced: | False |
| application.activity.enterArea.isExperimentalArea: | False |
| application.activity.enterArea.isPlantation: | True |
| application.activity.enterArea.isTreeNursery: | False |
| application.activity.enterArea.knownToBeProhibited: | True |
Then expect
Given these inputs
| @id: | qny2geqQe4pNOp7YeGvvl5Wl |
| @type: | Regsoft |
| @name: | Not entering restricted area = no permit required |
| application.forestArea.areaIsFenced: | False |
| application.forestArea.isExperimentalArea: | True |
| application.forestArea.isPlantation: | False |
| application.forestArea.isTreeNursery: | False |
| application.forestArea.knownToBeProhibited: | False |
| application.activity.enterArea.areaIsFenced: | True |
| application.activity.enterArea.isExperimentalArea: | False |
| application.activity.enterArea.isPlantation: | False |
| application.activity.enterArea.isTreeNursery: | False |
| application.activity.enterArea.knownToBeProhibited: | False |
Then expect
Given these inputs
| @id: | H4cj2ZRXvgOiPaf9nuhbg8m8 |
| @type: | Regsoft |
| @name: | Not interfering does not require a permit |
| application.equipmentToInterfereWith.isForExperimentation: | False |
| application.equipmentToInterfereWith.isUsedInConnectionWithResearchActivities: | False |
Then expect
Given these inputs
| @id: | H4cj2ZRXvgOiPaf9nuhbg8m8 |
| @type: | Regsoft |
| @name: | Not interfering does not require a permit |
| application.equipmentToInterfereWith.isForExperimentation: | True |
| application.equipmentToInterfereWith.isUsedInConnectionWithResearchActivities: | True |
Then expect
Given these inputs
| @id: | H4cj2ZRXvgOiPaf9nuhbg8m8 |
| @type: | Regsoft |
| @name: | Not interfering does not require a permit |
| application.equipmentToInterfereWith.isForExperimentation: | True |
| application.equipmentToInterfereWith.isUsedInConnectionWithResearchActivities: | False |
Then expect
Given these inputs
| @id: | AT4rIdcnyHt0o8adZsP3zKUZ |
| @type: | Regsoft |
| @name: | Not selling goods does not require a permit |
| application.sellGoodsOrServices: | False |
Then expect
Given these inputs
| @id: | s0YjBa6nEECpMj9sTVznK6MW |
| @type: | Regsoft |
| @name: | Selling goods requires a permit |
| application.sellGoodsOrServices: | True |
| application.activity.sellGoodsOrServices: | True |
Then expect
Given these inputs
| @id: | cBh7YLaZjGoUChfZJeYjWNTd |
| @type: | Regsoft |
| @name: | Not grazing does not require a licence |
| application.enterForestWithCattle: | False |
Then expect
Given these inputs
| @id: | 77aePcGrPkdDar3OxuSpyxqk |
| @type: | Regsoft |
| @name: | Entering with cattle requires a licence |
| application.enterForestWithCattle: | True |
| application.activity.enterForestWithCattle: | True |
Then expect
Given these inputs
| @id: | IGdismlXnANaGE5uv5A89nCa |
| @type: | Regsoft |
| @name: | Information not required if not applying for licence |
| application.isAdditionalActivityRequested: | False |
| application.isGatePermitRequired: | False |
| application.isGrazingLicenceRequired: | False |
| application.isPermitToEnterForestWithCattleRequired: | False |
| application.isPermitToInterfereWithResearchActivityRequired: | False |
| application.isPermitToSellRequired: | False |
| application.isRestrictedAreaPermitRequired: | False |
| application.isTreeFellingLicenceRequired: | False |
Then expect
Given these inputs
| @id: | S3GGBDe83rRcLZqHMhahF63I |
| @type: | Regsoft |
| @name: | Data required for licence |
| application.isAdditionalActivityRequested: | False |
| application.isGatePermitRequired: | True |
| application.isGrazingLicenceRequired: | False |
| application.isPermitToEnterForestWithCattleRequired: | False |
| application.isPermitToInterfereWithResearchActivityRequired: | False |
| application.isPermitToSellRequired: | False |
| application.isRestrictedAreaPermitRequired: | False |
| application.isTreeFellingLicenceRequired: | False |
Then expect
Nothing asserted — this scenario has no expectations.
Given these inputs
| @id: | iu7N0WLfzF5C6JDBOSZgPQm1 |
| @type: | Regsoft |
| @name: | Not cutting does not require a licence |
| application.cutDigOrTakeAwayForestProduce: | False |
| application.activity.cutDigOrTakeAwayForestProduce: | False |
Then expect
Given these inputs
| @id: | Jy01VlXXpN461UhzTj6Z5eMU |
| @type: | Regsoft |
| @name: | Removing forest produce needs a licence |
| application.cutDigOrTakeAwayForestProduce: | True |
| application.activity.cutDigOrTakeAwayForestProduce: | True |
Then expect
Given these inputs
| @id: | gPIKTADD8pIz4WkpkGtF2yXx |
| @type: | Regsoft |
| @name: | No additional activities does not require additional permissions |
| @id: | gKu5G8p5MiYiOxPEpxLQULju |
| @type: | Written authority |
| @name: | Test |
| @id: | gPIKTADD8pIz4WkpkGtF2yXx |
| Written authority.permittedAct: | Breakdancing |
| Written authority.personOrClassToWhomAuthorityApplies: | Everyone |
Then expect
1 · A grazing licence that’s never decided
The data model defines a “grazing licence required” conclusion, and the purpose test still checks for it — but no rule ever sets it. The gate section is even labelled “to decide if a grazier licence is required”, yet it switches on the gate permit. The grazing-licence path looks unfinished.
2 · The purpose check omits one permit (and keeps a phantom flag)
The computed isPurposeSpecified value ORs together eight of the nine requirement flags, but leaves out isPermitToTakeAwayForestProduceRequired (reg 10) — so an application whose only trigger is cutting or taking away forest produce is not recorded as needing a purpose. It also still ORs in the grazing flag from note 1, which no rule sets. Its Obligated modality, by contrast, is applied unconditionally.
3 · Duplicated and targetless requirement rules
The applicant’s name is made required in two places (the “Name” group and again under “8 Applications”), and the street number likewise appears twice. There is also a stray IS_REQUIRED rule with no target field at all, which does nothing. Harmless, but confusing for a future editor.
4 · An empty section
“9 Conditions of all licences and permits” contains no rules yet — a placeholder for logic not added.
5 · “Worked-out” flags labelled as user input
Several “is a permit required” flags (gate, tree-felling, restricted-area, research, sell, cattle-entry) are calculated by the rules but tagged in the data model as things the applicant enters (INPUT_DATA) — it works, but could mislead a reader or the question wizard.