mirror of
https://github.com/Hestia-Homes/assessment-model.git
synced 2026-07-27 22:45:03 +00:00
Merge pull request #433 from Hestia-Homes/docs/ara-projects-domain-language
docs(ara-projects): ADR-0018 + CONTEXT.md domain language (#405)
This commit is contained in:
commit
02f6dc265e
2 changed files with 116 additions and 2 deletions
32
CONTEXT.md
32
CONTEXT.md
|
|
@ -119,17 +119,45 @@ _Avoid_: property query, segment, search (the postcode-search journey is unrelat
|
|||
### Live projects
|
||||
|
||||
**Project**:
|
||||
A delivery programme within a Portfolio — a batch of Properties taken through retrofit together — identified by its HubSpot **project code** (`hubspot_deal_data.project_code`; a stable **project id** will replace the code once the HubSpot ops board is settled, so the code is the *current* identifier, not the essence). A Property whose deal carries no project code sits outside every Project (the "Unknown Project" grouping) and cannot be reached by selecting Projects.
|
||||
A delivery programme within a Portfolio — a batch of Properties taken through retrofit together — identified by its HubSpot **project code** (`hubspot_deal_data.project_code`; a stable **project id** will replace the code once the HubSpot ops board is settled, so the code is the *current* identifier, not the essence). A Property whose deal carries no project code sits outside every Project (the "Unknown Project" grouping) and cannot be reached by selecting Projects. Distinct from the **Ara Project** (next section) — the app-owned works programme that will eventually supersede this feature; where "Project" alone is ambiguous, say **HubSpot Project**. See [ADR-0018](./docs/adr/0018-ara-projects-supersedes-hubspot-live-projects.md).
|
||||
_Avoid_: programme, scheme, deal group, batch (a **Batch** is a separate per-deal field)
|
||||
|
||||
**Bulk document download**:
|
||||
An app-triggered, asynchronous assembly of a single ZIP of the documents held against a chosen set of Properties — picked as a row selection in the Documents tab, scoped by the tab's current Project/group — delivered as a time-limited link emailed to the requester (and, within the session, retrievable in-app). A selection that matches no documents produces no ZIP: it fails rather than emailing an empty archive. Properties are matched to their documents by **landlord property id**. See [ADR-0011](./docs/adr/0011-app-owned-task-marker-in-task-source.md).
|
||||
_Avoid_: bulk export, document export, zip download
|
||||
|
||||
### Ara Projects
|
||||
|
||||
The works-management module at top-level `/projects` (schema in `src/app/db/schema/projects/`, merged in PR #404). The strategic successor to the HubSpot-sourced "Live projects" feature above — both coexist for now, with no migration in v1. See [ADR-0018](./docs/adr/0018-ara-projects-supersedes-hubspot-live-projects.md) and the schema's own docs at `src/app/db/schema/projects/schema.md`.
|
||||
|
||||
**Project** (Ara):
|
||||
An organisation-owned works programme — the aggregate root of the Ara Projects module. Belongs to an `organisation` and is **many-to-many with Properties** (via `project_property`), unlike the HubSpot **Project** above (externally sourced, at most one per Property). Owns its **Project Workstreams**, which in turn own Stages, Evidence requirements and Contractor assignments. Where "Project" alone is ambiguous, say **Ara Project**.
|
||||
_Avoid_: programme, scheme, works package
|
||||
|
||||
**Workstream**:
|
||||
A category of works (Windows, Doors, Roofs, Electrical, Heating, …) — reference data in `workstream`, instantiated for one Ara Project as a **Project Workstream** (`project_workstream`), which owns its own Stage ladder, Evidence requirements and Contractor assignments.
|
||||
_Avoid_: measure (Measure is taken by the Scenarios domain), trade, work type
|
||||
|
||||
**Stage**:
|
||||
One step in a Project Workstream's ordered ladder (`project_workstream_stage`, positioned by `order`). Each Project Workstream owns its own ladder — different workstreams may follow different workflows. The v1 default ladder is Ordered / In progress / Completed / Charged / Closed, and the terminal stage is the one with the highest `order`. A Work order's stage FK (`work_order.project_workstream_stage_id`) is the **only lifecycle mechanism in v1** — `work_order.status`, `work_order.priority` and `project_workstream.current_stage_id` exist in the schema but are untouched.
|
||||
_Avoid_: status (the unused text column), phase, step
|
||||
|
||||
**Work order**:
|
||||
One unit of work issued to a contractor: a (Property, Project Workstream Stage, contractor organisation, unique reference, forecast end date) row in `work_order`. Its position in the workflow is its Stage FK (see **Stage**).
|
||||
_Avoid_: job, ticket, task (a **Task** is the BulkUpload orchestration handle)
|
||||
|
||||
**Evidence requirement** / **Evidence**:
|
||||
An **Evidence requirement** (`project_workstream_evidence_requirement`) is configuration: a required `file_type` (the existing enum) per Project Workstream, optionally narrowed to a single Stage. **Evidence** is a submission: an `uploaded_files` row with `file_source = 'projects'`, linked to its Work order (`work_order_id`) and optionally to the requirement it satisfies. Evidence is **advisory-only in v1** — badges and counts, never a gate: it does not block stage transitions and there is no approval state.
|
||||
_Avoid_: document (generic), attachment, proof
|
||||
|
||||
**Contractor**:
|
||||
An `organisation` assigned to a Project Workstream via `project_workstream_contractor`, carrying per-assignment `update_stages` / `upload_documents` permission flags — not a separate entity or table. Contractor users sign in through the existing `team` / `team_members` structures (each organisation gets a default team).
|
||||
_Avoid_: supplier, installer, vendor, subcontractor
|
||||
|
||||
### Tags
|
||||
|
||||
**Tag**:
|
||||
A user-created, coloured label owned by a Portfolio, used to form an arbitrary **group** of its Properties for bulk actions (e.g. running Scenarios over the group, or excluding it from a Reporting view). Flat (no hierarchy) and many-to-many: a Property carries zero or more Tags, and a Tag labels zero or more Properties. Distinct from a **Project** (a HubSpot-sourced grouping, at most one per Property) and from a **Scenario** (a modelling question): a Tag is an app-owned, hand-curated selection with no external source and no modelling semantics of its own.
|
||||
A user-created, coloured label owned by a Portfolio, used to form an arbitrary **group** of its Properties for bulk actions (e.g. running Scenarios over the group, or excluding it from a Reporting view). Flat (no hierarchy) and many-to-many: a Property carries zero or more Tags, and a Tag labels zero or more Properties. Distinct from a **HubSpot Project** (a HubSpot-sourced grouping, at most one per Property) and from a **Scenario** (a modelling question): a Tag is an app-owned, hand-curated selection with no external source and no modelling semantics of its own.
|
||||
_Avoid_: label, category, group (the group is the *effect* of a Tag, not a separate entity), segment, tag group
|
||||
|
||||
**Bulk tag assignment**:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
# 18. Ara Projects supersedes HubSpot Live projects, coexisting at top-level /projects
|
||||
|
||||
Date: 2026-07-21
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
Numbering note: 0015–0017 are in flight on the reporting-redesign branch
|
||||
(PR #416), alongside 0010; 0018 avoids collision with all of them (the same
|
||||
convention as ADR-0013's numbering note).
|
||||
|
||||
## Context
|
||||
|
||||
PR #404 merged the schema for a new works-management module
|
||||
(`src/app/db/schema/projects/`) whose aggregate root is called **Project**. But
|
||||
"Project" is already taken in our domain language: CONTEXT.md ("Live projects")
|
||||
and ADR-0013 define a Project as the HubSpot-sourced delivery grouping — at
|
||||
most one per Property, identified by `hubspot_deal_data.project_code`, served
|
||||
by the existing `/portfolio/[slug]/your-projects` feature.
|
||||
|
||||
The two are not one concept wearing two names — they differ on every axis:
|
||||
|
||||
- **HubSpot Project**: externally owned, read-only in the app, at most one per
|
||||
Property, no internal structure beyond membership.
|
||||
- **Ara Project**: app-owned, organisation-scoped, many-to-many with
|
||||
Properties, and structured — it carries configuration (Workstreams, Stages,
|
||||
Evidence requirements) and operational data (Contractor assignments, Work
|
||||
orders).
|
||||
|
||||
Something had to give: rename the new module, converge the old feature into it
|
||||
now, or run both under disambiguated names.
|
||||
|
||||
## Decision
|
||||
|
||||
- **Ara Projects is the strategic successor** to the HubSpot "Live projects"
|
||||
feature (`your-projects`). Long-term, works delivery lives in Ara Projects
|
||||
and the HubSpot grouping is retired.
|
||||
- **Both coexist for now.** Convergence and data migration are explicitly out
|
||||
of scope for v1 — `your-projects` keeps working unchanged, and no Ara
|
||||
Projects work may depend on changing it. Retiring it gets its own ADR when
|
||||
it is actually scheduled.
|
||||
- **The route namespace is top-level `/projects`**, with its own layout — not
|
||||
under the portfolio chrome. An Ara Project belongs to an `organisation` and
|
||||
spans Properties without regard to Portfolio boundaries, so
|
||||
`/portfolio/[slug]/...` is the wrong scope; it would also collide with the
|
||||
very feature it supersedes.
|
||||
- **Domain language is disambiguated in CONTEXT.md** (Ara Projects section):
|
||||
where "Project" alone is ambiguous, qualify — **HubSpot Project** vs
|
||||
**Ara Project**. The Ara Projects glossary terms (Workstream, Stage, Work
|
||||
order, Evidence requirement, Evidence, Contractor) match
|
||||
`src/app/db/schema/projects/schema.md` and are used verbatim by all Ara
|
||||
Projects issues (#405–#429).
|
||||
- **ADR-0013 is unaffected**: its contrast of Tags with "Projects"
|
||||
(HubSpot-owned, one-per-Property, not user-editable) refers to HubSpot
|
||||
Projects and remains correct as written.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
- **Rename the new module** (Programmes, Works, Schemes). Avoids the clash
|
||||
permanently, but the merged schema, the product and the business all say
|
||||
"Project" — a rename trades a bounded period of ambiguity for a permanent
|
||||
mismatch with the business vocabulary, and it protects the name of the
|
||||
feature that is scheduled to disappear.
|
||||
- **Converge now** — migrate `your-projects` data into Ara Projects in v1.
|
||||
Removes the coexistence cost, but front-loads a migration out of an
|
||||
externally-owned system before the new module has proven its shape, and
|
||||
couples v1 delivery to HubSpot ops decisions (the project-code → project-id
|
||||
switch is itself still pending on the HubSpot side).
|
||||
- **Nest under the portfolio chrome** (`/portfolio/[slug]/projects`). Matches
|
||||
where the old feature lives, but imposes a Portfolio scope the aggregate
|
||||
doesn't have, and makes the old and new features near-indistinguishable in
|
||||
the URL while both exist.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Two meanings of "Project" coexist in code and conversation until
|
||||
`your-projects` is retired. The mitigation is linguistic and enforced by
|
||||
review: CONTEXT.md is canonical, and ambiguous uses get qualified.
|
||||
- `/projects` becomes a reserved top-level namespace (it was unused before
|
||||
this decision).
|
||||
- Existing HubSpot-Project surfaces (the "Unknown Project" grouping, the
|
||||
Documents tab's Project scoping for Bulk document download) continue to mean
|
||||
HubSpot Projects; nothing there is renamed.
|
||||
- The eventual retirement of `your-projects` will need its own ADR covering
|
||||
data migration and user transition; nothing in v1 begins or blocks it.
|
||||
Loading…
Add table
Reference in a new issue