license: built full stack, test and documentation
Some checks failed
docs / build (push) Has been cancelled
docs / deploy (push) Has been cancelled

This commit is contained in:
Giuseppe Naponiello
2026-07-03 12:47:47 +02:00
parent f8206b5840
commit 271acacb1d
39 changed files with 4078 additions and 57 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

17
docs/developer/index.md Normal file
View File

@@ -0,0 +1,17 @@
# Developer guide
Architecture, data model and API of the Dynamic Collection platform, for
developers and integrators.
At a glance: an API-only **Laravel** backend (Sanctum + Fortify, MySQL,
Redis/Horizon), a **Vite + TypeScript** multi-page frontend with islands
(Tailwind v4 + daisyUI, Leaflet, 3DHOP), and a **Linked Art** provider
exposing records for harvesting by the Swedish national aggregator
(KSamsök 2).
## Chapters
- **[Licenses](licenses.md)** — the license vocabulary: data model, seeding,
legal text files, REUSE constraints and API endpoints.
*More chapters will follow as the platform takes shape.*

View File

@@ -0,0 +1,67 @@
# Licenses
The license vocabulary: data model, seeding, legal text files and API. For
the user-facing overview see the [User guide](../user/licenses.md).
## Data model
Licenses are a controlled vocabulary (table `licenses`, model
`App\Models\Lists\License`), created and populated at install time by the
`LicenseSeeder`**not** by the v1 ETL.
| Column | Meaning |
|---|---|
| `name` | Official full name (e.g. *Attribution 4.0 International*) |
| `acronym` | Display label shown in the UI (e.g. *CC BY 4.0*) |
| `spdx_id` | [SPDX](https://spdx.org/licenses/) identifier for export and interoperability; `NULL` for entries outside the SPDX License List — never invent one |
| `kind` | Backed enum `App\Enums\LicenseKind`: `license`, `mark` or `rights_statement` |
| `description` | One-sentence explanation shown in the forms |
| `uri` | Canonical URI (creativecommons.org / rightsstatements.org), also used in the Linked Art JSON-LD |
| `file` | File name of the legal text bundled in media download zips; `NULL` where no legal text exists |
| `for_record` / `for_media` | Scope flags: records only accept open licenses (CC0, CC BY), media accept everything |
| `sort_order` | Ordering in selects, from the most open to the most restrictive |
| `active` | Soft retirement: an inactive license disappears from forms but stays valid for content already using it |
Scope and `active` filtering happens in the form selects **and** is
re-validated server side; an edit form must still include the currently
assigned license even when it is inactive or out of scope.
## Seeding and legacy ids
The seeder ships 11 entries: Public Domain Mark + the CC 4.0 family + the
three most common rights statements (*InC*, *InC-EDU*, *CNE*). Ids **13 are
fixed** and match the legacy v1 database (1 = PDM, 2 = CC0, 3 = CC BY) so the
ETL maps artifact/media foreign keys 1:1 without translation. Further entries
can be added by administrators at runtime.
## Legal texts and downloads
The official CC legal texts live in
**`backend/storage/app/public/licenses/`**, named after their SPDX id
(e.g. `CC-BY-4.0.txt`). They are versioned in the repository — an exception
in `storage/app/public/.gitignore` — so they exist from the first clone. From
there the backend bundles them into media download zips, and the frontend can
link them directly (`/storage/licenses/…`, via `php artisan storage:link`).
Marks and rights statements have no legal text (`file` is `NULL`): the zip
only carries their canonical URI.
!!! warning "REUSE"
The root `LICENSES/` directory is reserved for the licenses **of the
repository**: [REUSE](https://reuse.software) fails the lint on license
texts not referenced by any file ("unused license"), and duplicate SPDX
file names anywhere under `LICENSES/` crash the tool. That is why the
downloadable texts live under `backend/storage/`. Their provenance is
annotated in `REUSE.toml`: Creative Commons dedicates the text of its
licenses to the public domain (CC0), which is also why `LICENSES/`
contains `CC0-1.0.txt`.
## API
| Endpoint | Access | Purpose |
|---|---|---|
| `GET /api/licenses` | public | list; filters `scope=record\|media`, `active=0\|1` |
| `GET /api/licenses/{id}` | public | detail |
| `GET /api/licenses/{id}/usage` | authenticated | is the license in use? |
| `POST /api/licenses` | admin | create an entry |
| `PUT/PATCH /api/licenses/{id}` | admin | update (partial updates supported, e.g. only `active`) |
| `DELETE /api/licenses/{id}` | admin | delete; blocked with `409` when the entry is in use |

22
docs/index.md Normal file
View File

@@ -0,0 +1,22 @@
# Dynamic Collection
User and technical documentation for the **Dynamic Collection** platform
(version 2).
Dynamic Collection is a platform for cataloguing and curating digital
collections of archaeological artifacts, developed by the
[DARKLab](https://www.darklab.lu.se/) at Lund University. Version 2 exposes
its data through the **KSamsök 2 Linked Art** harvesting standard of the
Swedish National Heritage Board (Riksantikvarieämbetet, RAÄ), so that records
can be collected by the Swedish national aggregator.
!!! note "Work in progress"
This documentation is being written alongside the rewrite of the
platform: sections will appear as the corresponding features land.
## Where to go
- **[User guide](user/index.md)** — for cataloguers, curators and
administrators working with collections through the web interface.
- **[Developer guide](developer/index.md)** — architecture, data model and
API reference for developers and integrators.

View File

@@ -0,0 +1,29 @@
/* Brand alignment with the Dynamic Collection application
(see frontend/src/styles/main.css: --dc-primary, --dc-secondary). */
@import url('https://fonts.googleapis.com/css2?family=Rajdhani:wght@500;700&display=swap');
:root {
/* --dc-primary rgb(34, 69, 138) */
--md-primary-fg-color: #22458a;
--md-primary-fg-color--light: #4a6cb0;
/* --dc-primary-dark rgb(0, 15, 46) */
--md-primary-fg-color--dark: #000f2e;
/* --dc-secondary-dark rgb(241, 146, 4) — links/hover accents */
--md-accent-fg-color: #f19204;
}
[data-md-color-scheme='slate'] {
--md-primary-fg-color: #22458a;
--md-accent-fg-color: #f9b958;
}
/* Display font for headings and site title, consistent with the app logo. */
.md-typeset h1,
.md-typeset h2,
.md-typeset h3,
.md-typeset h4,
.md-header__topic {
font-family: 'Rajdhani', 'Titillium Web', ui-sans-serif, system-ui, sans-serif;
font-weight: 700;
}

11
docs/user/index.md Normal file
View File

@@ -0,0 +1,11 @@
# User guide
How to work with Dynamic Collection through the web interface: cataloguing
artifacts and 3D models, uploading media, and administering the platform.
## Chapters
- **[Licenses](licenses.md)** — how records and media are licensed, which
options are available, and how to choose the right one.
*More chapters will follow as the platform takes shape.*

66
docs/user/licenses.md Normal file
View File

@@ -0,0 +1,66 @@
# Licenses
Every **record** (artifact or 3D model) and every **media file** (image,
document, video) in Dynamic Collection carries a license that tells the world
what can be done with it. This chapter explains the available options and how
to choose.
## Not everything is a license
The platform distinguishes three kinds of entries:
- **Licenses** grant permissions: the Creative Commons family (CC0, CC BY,
…). Choosing one tells reusers exactly what they are allowed to do.
- **The Public Domain Mark** (PDM) declares that a work is *already* free of
known copyright — for instance because copyright has expired. It grants
nothing new; it labels an existing status.
- **Rights statements** ([RightsStatements.org](https://rightsstatements.org))
label media that are closed or whose status is uncertain. Copyrighted
material is not "licensed": it is labelled with one of these (e.g. *In
Copyright*).
## Records vs media
**Records** must stay open — that is the point of publishing them — so only
**CC0 1.0** and **CC BY 4.0** can be selected. **Media files** may need the
full range, including closed options: a photograph may be under copyright
even when the record describing the artifact is open.
The forms only offer the options valid for what you are editing.
!!! note "Editing existing content"
An edit form always includes the currently assigned license, even if an
administrator has since retired it: you are never forced to change the
license of existing content just to save an unrelated edit.
## Available options
From the most open to the most restrictive:
| Option | Kind | What it means |
|---|---|---|
| PDM 1.0 | mark | Already free of known copyright worldwide (e.g. expired). |
| CC0 1.0 | license | The rights holder waives all rights: any use, no attribution required. |
| CC BY 4.0 | license | Any use, including commercial, with credit to the creator. |
| CC BY-SA 4.0 | license | Like CC BY, but derivatives must keep the same license. |
| CC BY-NC 4.0 | license | Reuse with attribution, non-commercial only. |
| CC BY-NC-SA 4.0 | license | Non-commercial, with attribution, same license on derivatives. |
| CC BY-ND 4.0 | license | Redistribution with attribution, but no derivative works. |
| CC BY-NC-ND 4.0 | license | Most restrictive CC: share with credit, no changes, no commercial use. |
| InC | rights statement | In copyright, all rights reserved: reuse requires permission. |
| InC-EDU | rights statement | In copyright, but educational use is permitted. |
| CNE | rights statement | Copyright not evaluated yet: treat as potentially protected. |
Each option shows a short explanation in the form when selected. When media
are downloaded, the zip archive includes the full legal text of the license
(for CC licenses) or the canonical URI of the statement.
## For administrators
Licenses are managed from the admin panel:
- **Add** further entries when needed — for example other RightsStatements.org
statements (*InC-NC*, *NoC-NC*, *NKC*, *UND*, …).
- **Retire** an option by deactivating it: it disappears from the forms but
remains valid for the content that already uses it. This is always
preferable to deletion, which is only possible for entries not in use.