From ffd79f245030a6967ec7a5184c5f78454e64e072 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Wed, 27 May 2026 11:30:24 -0600 Subject: [PATCH 01/67] docs(demo): add end-to-end demo presentation and tutorial Add docs/demo with a Marp presentation that doubles as a self-guided tutorial, covering the full NDP journey for end users and admins: installation from scratch, identity and permissions (AAI + Affinities), using the Endpoint from the web, automating with the Python library, federation, and the secure network (NetBird) as a bonus. Includes a README with rendering instructions and a screenshot checklist. Content will be refined incrementally. Refs #179 --- docs/demo/NDP-demo-presentation.md | 491 +++++++++++++++++++++++++++++ docs/demo/README.md | 67 ++++ docs/demo/screenshots/.gitkeep | 0 3 files changed, 558 insertions(+) create mode 100644 docs/demo/NDP-demo-presentation.md create mode 100644 docs/demo/README.md create mode 100644 docs/demo/screenshots/.gitkeep diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md new file mode 100644 index 0000000..d45fa5a --- /dev/null +++ b/docs/demo/NDP-demo-presentation.md @@ -0,0 +1,491 @@ +--- +marp: true +title: NDP β€” From zero to a federated, secure dataset +author: Raul Bardaji +paginate: true +theme: default +class: lead +--- + +" are speaker notes for whoever presents. +============================================================================== +--> + +# National Data Platform (NDP) +## From zero to a federated, secure dataset + +A guided demo of every component and how they work together + + + +--- + +## What is NDP? + +A platform to **publish, discover and share data** across institutions. + +- Each institution runs its own **Endpoint (EP)**: its data catalog. +- EPs are **federated**: discovered and shared through a central registry. +- All with shared **identity and permissions** and, optionally, over a + **secure private network**. + +> Key idea: **distributed data, unified discovery.** + + + +--- + +## The pieces (what we will see) + +| Piece | What it is for | How it looks | +|---|---|---| +| **AAI** (Keycloak) | Who you are (login, users) | Login screen | +| **Affinities** | Which group you belong to and your **role** | Groups web app | +| **NDP-EP** | Your catalog: datasets, resources, storage | Endpoint web app | +| **Federation** | Central registry of all EPs | Federation web app | +| **Python library** | Do the same from code / automate | Notebook / script | +| **NetBird** (bonus) | Secure private network between machines | Network dashboard | + +[πŸ“Έ screenshots/00-component-logos.png β€” optional: icons/logos of each piece] + +--- + +## How they relate + +``` + [ User ] + β”‚ 1. login + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” 2. which group & which role? β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ AAI │◄───────────────────────────────►│ Affinities β”‚ + β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ 3. token (identity + role) + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” 4. publish / search data + β”‚ NDP-EP β”‚ (catalog + storage) + β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ + β”‚ 5. registers & reports health + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Federation β”‚ ◄── other EPs register here too + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + + (all of this can travel over a private NetBird network β€” final bonus) +``` + + + +--- + +## The story we will follow + +> **Ana** is new. We give her access, she publishes a dataset, automates it from +> code, and that data shows up in the federation β€” all securely. + +**Demo acts:** +1. Installation from scratch +2. Identity and permissions (Ana logs in and gets her role) +3. The Endpoint in action (publish and search from the web) +4. Automate with the Python library +5. Federation (the data is discovered elsewhere) +6. πŸ”’ Bonus: secure network with NetBird + +--- + +# Act 1 β€” Installation from scratch +### (for administrators) + + + +--- + +## Requirements + +- A machine with **Docker** and **Docker Compose**. +- Access to each component's repository. +- (Recommended) a domain if you will expose services to the outside. + +> In development, **everything fits on a single machine**. In production, each +> component can live on its own server (that is where NetBird comes in). + +--- + +## Startup order + +``` +1) AAI (Keycloak) β†’ identity first, everything depends on it +2) Affinities β†’ groups and roles +3) Federation β†’ central registry +4) NDP-EP (+ backends) β†’ catalog, connects to AAI and Federation + backends: CKAN Β· MongoDB Β· MinIO (S3 storage) +``` + +Each component starts the same way: enter its folder and `docker compose up -d`. + + + +--- + +## 1) Start AAI (identity) + +```bash +cd ndp-keycloak-aai-old +cp .env.example .env # set admin user/password +docker compose up -d +``` + +**What you will see:** the Keycloak admin console and the NDP login screen. + +[πŸ“Έ screenshots/10-keycloak-login.png β€” NDP "Welcome back" login screen] +[πŸ“Έ screenshots/11-keycloak-admin.png β€” Keycloak admin console (realm NDP)] + +--- + +## 2) Start Affinities (groups and roles) + +```bash +cd ndp-affinities +docker compose up -d +``` + +**What you will see (default URLs):** +- API: `http://localhost:8000/docs` +- **Affinities web app**: `http://localhost:3000` +- Database admin (pgAdmin): `http://localhost:5050` + +[πŸ“Έ screenshots/12-affinities-frontend.png β€” Affinities web app with groups] + +--- + +## 3) Start Federation (central registry) + +```bash +cd ndp-federation +docker compose up -d +``` + +**What you will see:** +- Web: `http://localhost:8020/ui/` +- API & docs: `http://localhost:8020/docs` + +[πŸ“Έ screenshots/13-federation-ui.png β€” federation web app (EP list, still empty)] + +--- + +## 4) Start the NDP-EP (+ backends) + +```bash +cd ep-api +cp .env.example .env # point to AAI, Affinities, Federation +docker compose up -d +``` + +Starts the Endpoint alongside its backends: **CKAN**, **MongoDB** and **MinIO** (S3). + +**What you will see:** +- **Endpoint web app**: `…/ep-api/ui/` +- API documentation: `…/ep-api/docs` + +[πŸ“Έ screenshots/14-ep-home.png β€” Endpoint home page (search)] + +--- + +## βœ… Check: everything is up + +```bash +docker ps # all containers "Up / healthy" +``` + +From here on we work **from the web** (and later from code). + +[πŸ“Έ screenshots/15-docker-ps.png β€” list of containers in Up state] + + + +--- + +# Act 2 β€” Identity and permissions +### Ana logs in and gets her role + +--- + +## Create the user (AAI) + +In the Keycloak console, the administrator creates **Ana's** user and sets a password. + +[πŸ“Έ screenshots/20-create-user.png β€” creating a user in Keycloak] + +> The user alone **cannot publish anything yet**: she needs a **role**. + +--- + +## Grant the role (Affinities) + +Ana is added to a **group** in Affinities. The group determines her **role** in the +Endpoint. + +[πŸ“Έ screenshots/21-affinities-group.png β€” Ana added to a group with the writer role] + +--- + +## The three roles + +| Role | Can… | +|---|---| +| πŸ‘οΈ **Viewer** | View and search data. **Read-only.** | +| ✏️ **Writer** | The above **+ create/edit** datasets, resources and **S3 management**. | +| πŸ› οΈ **Admin** | All of the above **+ administration** (dashboard, access requests). | + +> With no role assigned, a user can only see public data. **Secure by default.** + + + +--- + +# Act 3 β€” The Endpoint in action +### Publish and search from the web + +--- + +## Log in + +Ana opens the Endpoint web app and logs in with her AAI user. + +The home page is the **search**: the heart of the Endpoint. + +[πŸ“Έ screenshots/30-login-and-search.png β€” login + search page] + +--- + +## Create an organization + +From the **"+ New" β†’ Organization** menu, Ana creates the organization that will +group her data. + +[πŸ“Έ screenshots/31-create-organization.png β€” new organization form] + +--- + +## Publish a dataset + +**"+ New" β†’ Dataset**: Ana describes her dataset (title, description, tags…). + +[πŸ“Έ screenshots/32-create-dataset.png β€” new dataset form] + +--- + +## Add a resource + +A dataset can have resources of several kinds, all from **"+ New"**: + +- **URL** β€” a link to a file or service +- **S3** β€” an object in S3-style storage +- **Kafka** β€” a streaming data flow + +[πŸ“Έ screenshots/33-create-resource.png β€” creating a resource (S3/URL/Kafka)] + +--- + +## Search and find + +Ana (or anyone) searches by text, filters, and finds the just-published dataset. +On her own data, the **publish/delete** actions appear. + +[πŸ“Έ screenshots/34-search-results.png β€” search results with the dataset] + +--- + +## Permissions, live πŸ”‘ + +The same web app **looks different depending on your role**: + +- πŸ‘οΈ A **viewer** logs in, searches and looks β€” **does not see** "S3 Management" or "+ New". +- ✏️ A **writer** does see **"+ New"** and **"S3 Management"** (bucket/object management). +- πŸ› οΈ An **admin** also sees the **Dashboard** and the **access requests**. + +[πŸ“Έ screenshots/35-viewer-vs-writer.png β€” menu comparison: viewer vs writer] + + + +--- + +## Storage management (S3) β€” writers only + +**S3 Management** lets you create and manage buckets and objects. +It is a storage administration tool: **writers/admins only**. + +[πŸ“Έ screenshots/36-s3-management.png β€” S3 Management tool (buckets/objects)] + +--- + +# Act 4 β€” Automate with Python +### The same thing, from code + + + +--- + +## The `ndp-ep` library + +Everything you do in the web app can also be done **from code**, ideal for +automating or bulk-loading data. + +```bash +pip install ndp-ep +``` + +> Useful for researchers and teams loading data repeatedly. + +--- + +## Example: in a few lines + +```python +from ndp_ep import APIClient + +# 1. Connect to the Endpoint with your token +client = APIClient(base_url="https://my-endpoint/ep-api", token="…") + +# 2. List organizations +print(client.list_organizations()) + +# 3. Create a dataset and search for it +client.create_dataset(name="measurements-2026", owner_org="my-org") +print(client.search_datasets("measurements")) +``` + +[πŸ“Έ screenshots/40-notebook.png β€” Jupyter notebook running these steps] + + + +--- + +## The same data, two paths + +``` + Web (click) ─┐ + β”œβ”€β–Ί the SAME Endpoint ─► the SAME catalog + Python (code) β”€β”˜ +``` + +> Web for day-to-day, code to automate. **Same data, same permissions.** + +--- + +# Act 5 β€” Federation +### The data is discovered elsewhere + +--- + +## The Endpoint registers + +Each Endpoint registers with **Federation**. From then on, the central registry +knows it exists and watches its **status** and **metrics**. + +[πŸ“Έ screenshots/50-federation-ep-registered.png β€” the EP appears in the federation] + +--- + +## Health and metrics + +The federation web app shows which Endpoints are **alive**, since when, and with +what activity. + +[πŸ“Έ screenshots/51-federation-health.png β€” EP health/metrics panel] + +--- + +## Why it matters + +``` + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Federation β”‚ "the map of all the data" + β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β–Ό β–Ό β–Ό +[ EP Utah ] [ EP B ] [ EP C ] each institution, its catalog +``` + +> You search in one place and find data from **many** institutions. +> Each one keeps control of **its** data. + +--- + +# πŸ”’ Bonus β€” NetBird +### The secure network that ties it all together + +--- + +## The problem + +In production, each component lives on a **different machine**. +How do they talk **without** opening ports to the world? + +> Answer: a **private encrypted network** (mesh VPN) connecting only our machines. + +--- + +## The solution: NetBird + +- Each machine gets a **stable private IP** on a virtual network. +- Traffic goes **directly and encrypted** between machines (WireGuard). +- You decide **who talks to whom**; everything else is blocked. +- **No public ports** for the services. + +[πŸ“Έ screenshots/60-netbird-peers.png β€” NetBird dashboard with connected machines (peers)] + +--- + +## Demonstrated + +Two machines on the network: one **reaches all the NDP services** of the other +(EP, Federation, Affinities, AAI…) **only over the encrypted tunnel**, with no +public ports. + +[πŸ“Έ screenshots/61-netbird-access.png β€” proof of access to the services over the mesh] + +> This is exactly the production multi-machine scenario, already validated. + +--- + +# Wrap-up + +--- + +## The story at a glance + +1. We **installed** NDP from scratch (Docker). +2. Ana **logged in** (AAI) and received her **role** (Affinities). +3. She **published and searched** data from the Endpoint **web app**. +4. She did the same **from code** with the Python library. +5. The data was **federated** and is discovered elsewhere. +6. Everything can run over a **secure network** (NetBird). + +> **Distributed data, unified discovery, governed and secure access.** + +--- + +## Resources + +- **Endpoint (web):** `…/ep-api/ui/` Β· **API:** `…/ep-api/docs` +- **Federation:** `…:8020/ui/` +- **Affinities:** `…:3000` +- **Python library:** `pip install ndp-ep` Β· PyPI: `ndp-ep` +- **Repos:** `ep-api`, `ndp-federation`, `ndp-affinities`, `ndp-keycloak-aai-old`, `ndp-ep-py`, `netbird-ndp` + +--- + +# Thank you! +## Questions + + diff --git a/docs/demo/README.md b/docs/demo/README.md new file mode 100644 index 0000000..7c444e3 --- /dev/null +++ b/docs/demo/README.md @@ -0,0 +1,67 @@ +# NDP demo β€” presentation & self-guided tutorial + +End-to-end material that walks through the whole NDP system (installation, web +usage, the Python library, federation and the secure network), aimed at **end +users and administrators**. + +## Files + +- `NDP-demo-presentation.md` β€” the presentation in **Marp** format. It doubles as + a self-guided tutorial: each step states what to do and what you will see. +- `screenshots/` β€” drop the screenshots here (see the checklist below). + +## Turning it into slides + +**Option A β€” VS Code (easiest):** install the **"Marp for VS Code"** extension, +open `NDP-demo-presentation.md` and click the preview icon. From there you can +export to **PDF**, **PPTX** (PowerPoint) or **HTML**. + +**Option B β€” command line (Marp CLI):** + +```bash +npx @marp-team/marp-cli NDP-demo-presentation.md -o NDP-demo-presentation.pdf +npx @marp-team/marp-cli NDP-demo-presentation.md --pptx -o NDP-demo-presentation.pptx +npx @marp-team/marp-cli NDP-demo-presentation.md -o NDP-demo-presentation.html +``` + +## Screenshots to capture + +Each `[πŸ“Έ screenshots/NN-name.png …]` placeholder in the presentation maps to one +screenshot. Checklist: + +**Installation** +- [ ] `10-keycloak-login.png` β€” NDP login (Keycloak) +- [ ] `11-keycloak-admin.png` β€” Keycloak admin console (realm NDP) +- [ ] `12-affinities-frontend.png` β€” Affinities web app with groups +- [ ] `13-federation-ui.png` β€” federation web app (still empty) +- [ ] `14-ep-home.png` β€” Endpoint home page (search) +- [ ] `15-docker-ps.png` β€” `docker ps` with everything "Up" + +**Identity and permissions** +- [ ] `20-create-user.png` β€” creating a user in Keycloak +- [ ] `21-affinities-group.png` β€” user added to a group with the writer role + +**Endpoint (web)** +- [ ] `30-login-and-search.png` β€” login + search +- [ ] `31-create-organization.png` β€” new organization +- [ ] `32-create-dataset.png` β€” new dataset +- [ ] `33-create-resource.png` β€” new resource (S3/URL/Kafka) +- [ ] `34-search-results.png` β€” results with the dataset +- [ ] `35-viewer-vs-writer.png` β€” viewer vs writer menu (the key contrast) +- [ ] `36-s3-management.png` β€” S3 Management tool + +**Python** +- [ ] `40-notebook.png` β€” notebook running the library + +**Federation** +- [ ] `50-federation-ep-registered.png` β€” the EP in the federation +- [ ] `51-federation-health.png` β€” health/metrics + +**NetBird (bonus)** +- [ ] `60-netbird-peers.png` β€” dashboard with connected peers +- [ ] `61-netbird-access.png` β€” accessing services over the mesh + +## Notes + +- Presentation text (and speaker notes ``) are in **English**. +- This material is written and refined incrementally (see issue #179). diff --git a/docs/demo/screenshots/.gitkeep b/docs/demo/screenshots/.gitkeep new file mode 100644 index 0000000..e69de29 From cf05e8eaa25e964adb8e7263dd5cd2aeef3c19f3 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Wed, 27 May 2026 11:44:02 -0600 Subject: [PATCH 02/67] docs(demo): apply brand header/footer from official pptx Reuse the NDP logo (header) and partner-logo band (footer) from 'ndp ep - presentation.pptx' as layered slide backgrounds via CSS, so every slide carries the official branding. Document the assets and the --allow-local-files flag needed when exporting. Refs #179 --- docs/demo/NDP-demo-presentation.md | 24 ++++++++++++++++++++++++ docs/demo/README.md | 9 +++++++-- docs/demo/assets/footer-left.png | Bin 0 -> 67356 bytes docs/demo/assets/footer-right.png | Bin 0 -> 39164 bytes docs/demo/assets/header-logo.png | Bin 0 -> 10989 bytes 5 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 docs/demo/assets/footer-left.png create mode 100644 docs/demo/assets/footer-right.png create mode 100644 docs/demo/assets/header-logo.png diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index d45fa5a..f920919 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -18,6 +18,30 @@ class: lead ============================================================================== --> + + # National Data Platform (NDP) ## From zero to a federated, secure dataset diff --git a/docs/demo/README.md b/docs/demo/README.md index 7c444e3..2e6b5cd 100644 --- a/docs/demo/README.md +++ b/docs/demo/README.md @@ -8,6 +8,8 @@ users and administrators**. - `NDP-demo-presentation.md` β€” the presentation in **Marp** format. It doubles as a self-guided tutorial: each step states what to do and what you will see. +- `assets/` β€” brand header/footer images (NDP logo + partner logos) reused from + the official `ndp ep - presentation.pptx`. Applied to every slide via CSS. - `screenshots/` β€” drop the screenshots here (see the checklist below). ## Turning it into slides @@ -19,11 +21,14 @@ export to **PDF**, **PPTX** (PowerPoint) or **HTML**. **Option B β€” command line (Marp CLI):** ```bash -npx @marp-team/marp-cli NDP-demo-presentation.md -o NDP-demo-presentation.pdf -npx @marp-team/marp-cli NDP-demo-presentation.md --pptx -o NDP-demo-presentation.pptx +# --allow-local-files is required because the brand header/footer use local images +npx @marp-team/marp-cli --allow-local-files NDP-demo-presentation.md -o NDP-demo-presentation.pdf +npx @marp-team/marp-cli --allow-local-files NDP-demo-presentation.md --pptx -o NDP-demo-presentation.pptx npx @marp-team/marp-cli NDP-demo-presentation.md -o NDP-demo-presentation.html ``` +> Run these from inside `docs/demo/` so the `assets/...` paths resolve. + ## Screenshots to capture Each `[πŸ“Έ screenshots/NN-name.png …]` placeholder in the presentation maps to one diff --git a/docs/demo/assets/footer-left.png b/docs/demo/assets/footer-left.png new file mode 100644 index 0000000000000000000000000000000000000000..7f90de91e8e7382801caca133b1f9bf253bc9f5a GIT binary patch literal 67356 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 >!EzvV0Cp<59oHzbo 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 literal 0 HcmV?d00001 From a9d39a243120be2d07ad163c223de777e1ea6c0c Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Wed, 27 May 2026 11:52:25 -0600 Subject: [PATCH 03/67] docs(demo): add SVG component icons and use them in the pieces slide Hand-crafted minimal SVG icons (NDP navy) for AAI, Affinities, NDP-EP, Federation, Python library and NetBird; shown next to each component in the 'pieces' slide. Removes the component-logos screenshot placeholder. Refs #179 --- docs/demo/NDP-demo-presentation.md | 16 ++++++---------- docs/demo/assets/icons/aai.svg | 8 ++++++++ docs/demo/assets/icons/affinities.svg | 11 +++++++++++ docs/demo/assets/icons/federation.svg | 13 +++++++++++++ docs/demo/assets/icons/ndp-ep.svg | 10 ++++++++++ docs/demo/assets/icons/netbird.svg | 16 ++++++++++++++++ docs/demo/assets/icons/python-lib.svg | 8 ++++++++ 7 files changed, 72 insertions(+), 10 deletions(-) create mode 100644 docs/demo/assets/icons/aai.svg create mode 100644 docs/demo/assets/icons/affinities.svg create mode 100644 docs/demo/assets/icons/federation.svg create mode 100644 docs/demo/assets/icons/ndp-ep.svg create mode 100644 docs/demo/assets/icons/netbird.svg create mode 100644 docs/demo/assets/icons/python-lib.svg diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index f920919..b5f2033 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -8,14 +8,12 @@ class: lead --- " are speaker notes for whoever presents. -============================================================================== --> - - - - - - - - - + + + PLATFORM SERVICES - - - browse / search - routes /ep-api/* - validate tokens - catalog (CKAN API) - register affinities - report metrics + + + + + + + + + + + browse / search + routes /ep-api/* + validate tokens + catalog API + register affinities + report metrics - + - - - Data User - / Administrator + + + + + + Data User + / Administrator - - - - Nginx proxy - single entry Β· :80 + + + + + + + + + + Nginx + single entry Β· :80 - - - - NDP-EP - Unified REST API - datasets Β· search Β· storage + + + + + + + + + + + + + NDP-EP + Unified REST API + datasets Β· search Β· storage + + + + + + + + + + + + Identity & Access + Keycloak + AAI Β· tokens & roles + + + + + + + + + + + + CKAN + local data catalog + + + + + + + + Affinities + relationships graph - - - - - Identity & Access (AAI) - Keycloak + AAI Β· tokens & roles - - - CKAN - local data catalog - - - Affinities - relationships graph - - - Federation - endpoint registry Β· health + + + + + + + Federation + endpoint registry Β· health From 4aa0faf499c6bddbc98235199d66fed6c0b10d76 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Wed, 27 May 2026 12:10:55 -0600 Subject: [PATCH 07/67] docs(demo): redraw component interactions as a linear journey Switch from an NDP-EP-centric hub to the original left-to-right/top-down flow: Data User -> AAI (+Affinities for role) -> NDP-EP (with CKAN/S3 backends) -> Federation, plus a NetBird footnote. Keeps the polished styling (shadows, icon badges, halo labels) without making the EP the center everything radiates from. Refs #179 --- docs/demo/NDP-demo-presentation.md | 10 +- .../diagrams/component-interactions.svg | 157 ++++++++---------- 2 files changed, 74 insertions(+), 93 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index 018cc60..ff291c1 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -80,13 +80,13 @@ A platform to **publish, discover and share data** across institutions. ## Component interactions -![w:880](assets/diagrams/component-interactions.svg) +![w:600](assets/diagrams/component-interactions.svg) -A single entry point routes to each service; the **NDP-EP** is the hub β€” it validates tokens (AAI), uses the catalog (CKAN), registers affinities, and reports metrics to the federation. +The user signs in through **AAI**; **Affinities** decides their role; with that token they publish and search in the **NDP-EP** (backed by **CKAN** and **S3**), which registers and reports to **Federation**. - + --- diff --git a/docs/demo/assets/diagrams/component-interactions.svg b/docs/demo/assets/diagrams/component-interactions.svg index 466ccb7..3b1dc6f 100644 --- a/docs/demo/assets/diagrams/component-interactions.svg +++ b/docs/demo/assets/diagrams/component-interactions.svg @@ -1,100 +1,90 @@ - + - + - + - - - PLATFORM SERVICES - - - - - - - + + + + + - browse / search - routes /ep-api/* - validate tokens - catalog API - register affinities - report metrics + log in + which group & role + token (identity + role) + register Β· report metrics + catalog + storage - - - - - - - Data User - / Administrator + + + + + Data User + / Administrator - - - - - - - - - + + + + + + - Nginx - single entry Β· :80 + AAI Β· Identity + Keycloak Β· tokens - - - + + + + + + - - - - - - - + Affinities + groups & roles + + + + + + - NDP-EP - Unified REST API - datasets Β· search Β· storage + NDP-EP + Endpoint Β· REST API + datasets Β· search - - - - + + + - - - - + + - Identity & Access - Keycloak + AAI Β· tokens & roles + Federation + endpoint registry - - - + + + @@ -102,26 +92,17 @@ - CKAN - local data catalog + CKAN Β· MinIO (S3) + catalog & object storage - - - - - - - - Affinities - relationships graph - - - - - - - + + + + + + + + Runs over a private + NetBird network - Federation - endpoint registry Β· health From 1f46463c74eb2d4bc4e85b07aac8f57bd3d0a019 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Wed, 27 May 2026 12:18:13 -0600 Subject: [PATCH 08/67] =?UTF-8?q?docs(demo):=20fix=20Affinities=20role=20?= =?UTF-8?q?=E2=80=94=20it=20is=20a=20relationship=20registry,=20not=20role?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Roles live entirely in AAI (Keycloak): the token carries ndp_writer/ ndp_admin/group:{uuid}:tier. Affinities is a non-blocking relationship registry the EP writes datasets/services/endpoints into. Correct the interactions diagram (Affinities is a write target of the EP, not between AAI and the EP), the pieces table, startup order, the Act 2 'grant role' slide (now AAI), captions and the summary. Refs #179 --- docs/demo/NDP-demo-presentation.md | 29 ++--- docs/demo/README.md | 4 +- .../diagrams/component-interactions.svg | 117 +++++++++--------- 3 files changed, 75 insertions(+), 75 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index ff291c1..b117c61 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -70,7 +70,7 @@ A platform to **publish, discover and share data** across institutions. | Piece | What it is for | How it looks | |---|---|---| | **AAI** (Keycloak) | Who you are (login, users) | Login screen | -| **Affinities** | Which group you belong to and your **role** | Groups web app | +| **Affinities** | Relationships between datasets, services and endpoints | Relationships web app | | **NDP-EP** | Your catalog: datasets, resources, storage | Endpoint web app | | **Federation** | Central registry of all EPs | Federation web app | | **Python library** | Do the same from code / automate | Notebook / script | @@ -80,13 +80,14 @@ A platform to **publish, discover and share data** across institutions. ## Component interactions -![w:600](assets/diagrams/component-interactions.svg) +![w:680](assets/diagrams/component-interactions.svg) -The user signs in through **AAI**; **Affinities** decides their role; with that token they publish and search in the **NDP-EP** (backed by **CKAN** and **S3**), which registers and reports to **Federation**. +The user signs in through **AAI**, which also carries their **role**. With that token they publish and search in the **NDP-EP** (backed by **CKAN** and **S3**). The EP then registers its datasets/services in **Affinities** and reports to **Federation**. - + --- @@ -128,7 +129,7 @@ a private NetBird network (final bonus). Derived from the C4 view in ../ep-diagr ``` 1) AAI (Keycloak) β†’ identity first, everything depends on it -2) Affinities β†’ groups and roles +2) Affinities β†’ relationships (data Β· services Β· endpoints) 3) Federation β†’ central registry 4) NDP-EP (+ backends) β†’ catalog, connects to AAI and Federation backends: CKAN Β· MongoDB Β· MinIO (S3 storage) @@ -155,7 +156,7 @@ docker compose up -d --- -## 2) Start Affinities (groups and roles) +## 2) Start Affinities (relationship registry) ```bash cd ndp-affinities @@ -167,7 +168,7 @@ docker compose up -d - **Affinities web app**: `http://localhost:3000` - Database admin (pgAdmin): `http://localhost:5050` -[πŸ“Έ screenshots/12-affinities-frontend.png β€” Affinities web app with groups] +[πŸ“Έ screenshots/12-affinities-frontend.png β€” Affinities web app (relationships graph)] --- @@ -233,12 +234,12 @@ In the Keycloak console, the administrator creates **Ana's** user and sets a pas --- -## Grant the role (Affinities) +## Grant the role (AAI) -Ana is added to a **group** in Affinities. The group determines her **role** in the -Endpoint. +In **AAI** (Keycloak), the administrator gives Ana a **role** β€” directly or by adding +her to a **group** that carries it. The role travels inside her token to the Endpoint. -[πŸ“Έ screenshots/21-affinities-group.png β€” Ana added to a group with the writer role] +[πŸ“Έ screenshots/21-assign-role.png β€” assigning the writer role/group in Keycloak] --- @@ -470,7 +471,7 @@ public ports. ## Summary 1. We **installed** NDP from scratch (Docker). -2. Ana **logged in** (AAI) and received her **role** (Affinities). +2. Ana **logged in** and received her **role** (both in AAI). 3. She **published and searched** data from the Endpoint **web app**. 4. She did the same **from code** with the Python library. 5. The data was **federated** and is discovered elsewhere. diff --git a/docs/demo/README.md b/docs/demo/README.md index 2e6b5cd..daf42c0 100644 --- a/docs/demo/README.md +++ b/docs/demo/README.md @@ -37,14 +37,14 @@ screenshot. Checklist: **Installation** - [ ] `10-keycloak-login.png` β€” NDP login (Keycloak) - [ ] `11-keycloak-admin.png` β€” Keycloak admin console (realm NDP) -- [ ] `12-affinities-frontend.png` β€” Affinities web app with groups +- [ ] `12-affinities-frontend.png` β€” Affinities web app (relationships graph) - [ ] `13-federation-ui.png` β€” federation web app (still empty) - [ ] `14-ep-home.png` β€” Endpoint home page (search) - [ ] `15-docker-ps.png` β€” `docker ps` with everything "Up" **Identity and permissions** - [ ] `20-create-user.png` β€” creating a user in Keycloak -- [ ] `21-affinities-group.png` β€” user added to a group with the writer role +- [ ] `21-assign-role.png` β€” assigning the writer role/group in Keycloak (AAI) **Endpoint (web)** - [ ] `30-login-and-search.png` β€” login + search diff --git a/docs/demo/assets/diagrams/component-interactions.svg b/docs/demo/assets/diagrams/component-interactions.svg index 3b1dc6f..3cadbe5 100644 --- a/docs/demo/assets/diagrams/component-interactions.svg +++ b/docs/demo/assets/diagrams/component-interactions.svg @@ -1,4 +1,4 @@ - + @@ -11,80 +11,60 @@ - - - - - + + + + + - log in - which group & role - token (identity + role) - register Β· report metrics - catalog + storage + log in + token (identity + role) + catalog + storage + register datasets & services + register Β· report metrics - - + + - Data User - / Administrator + Data User + / Administrator - - - + + + - AAI Β· Identity - Keycloak Β· tokens + AAI Β· Identity + Keycloak Β· tokens + roles - - - - - - - - Affinities - groups & roles - - - - + + + - NDP-EP - Endpoint Β· REST API - datasets Β· search - - - - - - - - - Federation - endpoint registry + NDP-EP + Endpoint Β· REST API + datasets Β· search Β· storage - - + + @@ -92,17 +72,36 @@ - CKAN Β· MinIO (S3) - catalog & object storage + CKAN Β· MinIO (S3) + catalog & object storage + + + + + + + + + Affinities + relationships: data Β· services Β· EPs + + + + + + + + + Federation + endpoint registry Β· health - - - - - + + + + + - Runs over a private - NetBird network + All of this can run over a private, encrypted NetBird network From fbc1cbae8b0b04b6ac7a723cfab032c28c553c04 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Wed, 27 May 2026 12:26:44 -0600 Subject: [PATCH 09/67] docs(demo): make component-interactions diagram horizontal Top row: Data User -> AAI -> NDP-EP; bottom row spread full width: CKAN/S3, Affinities, Federation (the EP writes to them). Wider aspect fills the slide and fixes the footnote overflowing off the bottom. Refs #179 --- docs/demo/NDP-demo-presentation.md | 2 +- .../diagrams/component-interactions.svg | 95 +++++++++---------- 2 files changed, 48 insertions(+), 49 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index b117c61..956e252 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -80,7 +80,7 @@ A platform to **publish, discover and share data** across institutions. ## Component interactions -![w:680](assets/diagrams/component-interactions.svg) +![w:1080](assets/diagrams/component-interactions.svg) The user signs in through **AAI**, which also carries their **role**. With that token they publish and search in the **NDP-EP** (backed by **CKAN** and **S3**). The EP then registers its datasets/services in **Affinities** and reports to **Federation**. diff --git a/docs/demo/assets/diagrams/component-interactions.svg b/docs/demo/assets/diagrams/component-interactions.svg index 3cadbe5..4c9e7c6 100644 --- a/docs/demo/assets/diagrams/component-interactions.svg +++ b/docs/demo/assets/diagrams/component-interactions.svg @@ -1,4 +1,4 @@ - + @@ -11,60 +11,59 @@ - - - - - + + + + + - log in - token (identity + role) - catalog + storage - register datasets & services - register Β· report metrics + log in + token (identity + role) + catalog + storage + registers data & services + register Β· report metrics - - + + - Data User - / Administrator + Data User - - - + + + - AAI Β· Identity - Keycloak Β· tokens + roles + AAI Β· Identity + Keycloak Β· tokens + roles - - - + + + - NDP-EP - Endpoint Β· REST API - datasets Β· search Β· storage + NDP-EP + Endpoint Β· REST API + datasets Β· search Β· storage - - - + + + @@ -72,36 +71,36 @@ - CKAN Β· MinIO (S3) - catalog & object storage + CKAN Β· MinIO (S3) + catalog & object storage - - - + + + - Affinities - relationships: data Β· services Β· EPs + Affinities + relationships graph - - - + + + - Federation - endpoint registry Β· health + Federation + endpoint registry Β· health - - - + + + - + - All of this can run over a private, encrypted NetBird network + All of this can run over a private, encrypted NetBird network From 1ec66623d0322ce728d419e0097cf7ee477e75c2 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Wed, 27 May 2026 12:28:13 -0600 Subject: [PATCH 10/67] docs(demo): move interactions explanation to speaker notes The paragraph overflowed the slide below the wide diagram. The diagram's own labels already tell the story, so keep the slide clean and move the narration into the speaker notes. Refs #179 --- docs/demo/NDP-demo-presentation.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index 956e252..b711b83 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -82,12 +82,12 @@ A platform to **publish, discover and share data** across institutions. ![w:1080](assets/diagrams/component-interactions.svg) -The user signs in through **AAI**, which also carries their **role**. With that token they publish and search in the **NDP-EP** (backed by **CKAN** and **S3**). The EP then registers its datasets/services in **Affinities** and reports to **Federation**. - - + --- From 5169c46f0b4a2f20a605c35d8b6843622e304a2a Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Wed, 27 May 2026 12:29:34 -0600 Subject: [PATCH 11/67] docs(demo): add a 'step by step' slide for component interactions Make the deck self-explanatory: keep the diagram slide clean and add a following slide that narrates the flow as numbered steps (sign in -> use the EP -> register relationships -> federate -> secure transport). Refs #179 --- docs/demo/NDP-demo-presentation.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index b711b83..8af564f 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -91,6 +91,19 @@ network (final bonus). Derived from the C4 view in ../ep-diagrams. --> --- +## Component interactions β€” step by step + +1. **Sign in** β€” the user authenticates through **AAI** (Keycloak), which also carries their **role** (viewer / writer / admin). +2. **Use the Endpoint** β€” with that token they publish and search in the **NDP-EP**, backed by **CKAN** (catalog) and **MinIO / S3** (storage). +3. **Register relationships** β€” the EP registers its datasets and services in **Affinities**, a non-blocking graph of how data, services and endpoints relate. +4. **Federate** β€” the EP reports to **Federation** (central registry + health & metrics). +5. **Secure transport** β€” all of it can run over a private, encrypted **NetBird** network. + + + +--- + ## Demo walkthrough > **Ana** is new. We give her access, she publishes a dataset, automates it from From de022dfd5280fe74b0de143f4c377a2a93dc601c Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Wed, 27 May 2026 12:35:30 -0600 Subject: [PATCH 12/67] docs(demo): de-personalize narrative and reframe installation - Remove the 'Ana' persona; use generic 'the user'. - Installation now leads with the common case (install only the NDP-EP and connect to the central NDP, which already runs AAI/Affinities/Federation); the full local stack is clearly marked as development/testing only. - Rename the 'Demo walkthrough' slide to 'Overview'. Refs #179 --- docs/demo/NDP-demo-presentation.md | 89 +++++++++++++++++++----------- 1 file changed, 56 insertions(+), 33 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index 8af564f..de971e9 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -104,14 +104,14 @@ registry the EP writes into; it is non-blocking (the EP works even if it is down --- -## Demo walkthrough +## Overview -> **Ana** is new. We give her access, she publishes a dataset, automates it from -> code, and that data shows up in the federation β€” all securely. +> A new user gets access, publishes a dataset, automates it from code, and that +> data shows up in the federation β€” all securely. **Demo acts:** -1. Installation from scratch -2. Identity and permissions (Ana logs in and gets her role) +1. Installation +2. Identity and permissions (sign in and get a role) 3. The Endpoint in action (publish and search from the web) 4. Automate with the Python library 5. Federation (the data is discovered elsewhere) @@ -119,26 +119,52 @@ registry the EP writes into; it is non-blocking (the EP works even if it is down --- -# Act 1 β€” Installation from scratch -### (for administrators) +# Act 1 β€” Installation - +--- + +## Two ways to install + +**🟒 Most users β€” just the NDP-EP** +Run your own **Endpoint** and connect it to the **National Data Platform**, which +already provides identity (**AAI**), **Affinities** and **Federation**. +β†’ you install **one** component. + +**πŸ§ͺ Full stack β€” development / testing** +Run *everything* on your own machine, with no dependency on the central NDP. +β†’ you install **all** components. + +> Next slide: the common case. The rest of Act 1: the full stack. --- -## Requirements +## Install the NDP-EP (the common case) + +```bash +cd ep-api +cp .env.example .env # point to the National Data Platform + # (its AAI, Affinities and Federation) +docker compose up -d +``` -- A machine with **Docker** and **Docker Compose**. -- Access to each component's repository. -- (Recommended) a domain if you will expose services to the outside. +You only run the **Endpoint** (plus its catalog/storage backends). Identity, +Affinities and Federation are the platform's **shared services** β€” already there. -> In development, **everything fits on a single machine**. In production, each -> component can live on its own server (that is where NetBird comes in). +**What you will see:** your Endpoint web app at `…/ep-api/ui/`. + +[πŸ“Έ screenshots/14-ep-home.png β€” Endpoint home page (search)] --- -## Startup order +# Full stack (development / testing) +### Only if you want the whole system locally + + + +--- + +## Startup order (full stack) ``` 1) AAI (Keycloak) β†’ identity first, everything depends on it @@ -204,17 +230,14 @@ docker compose up -d ```bash cd ep-api -cp .env.example .env # point to AAI, Affinities, Federation +cp .env.example .env # point to your LOCAL AAI, Affinities, Federation docker compose up -d ``` Starts the Endpoint alongside its backends: **CKAN**, **MongoDB** and **MinIO** (S3). -**What you will see:** -- **Endpoint web app**: `…/ep-api/ui/` -- API documentation: `…/ep-api/docs` - -[πŸ“Έ screenshots/14-ep-home.png β€” Endpoint home page (search)] +**What you will see:** the same Endpoint web app as before, now wired to your +local services β€” `…/ep-api/ui/` and API docs at `…/ep-api/docs`. --- @@ -233,13 +256,13 @@ From here on we work **from the web** (and later from code). --- # Act 2 β€” Identity and permissions -### Ana logs in and gets her role +### A user signs in and gets a role --- ## Create the user (AAI) -In the Keycloak console, the administrator creates **Ana's** user and sets a password. +In the Keycloak console, the administrator creates the **user** and sets a password. [πŸ“Έ screenshots/20-create-user.png β€” creating a user in Keycloak] @@ -249,8 +272,8 @@ In the Keycloak console, the administrator creates **Ana's** user and sets a pas ## Grant the role (AAI) -In **AAI** (Keycloak), the administrator gives Ana a **role** β€” directly or by adding -her to a **group** that carries it. The role travels inside her token to the Endpoint. +In **AAI** (Keycloak), the administrator gives the user a **role** β€” directly or by +adding them to a **group** that carries it. The role travels inside the token to the Endpoint. [πŸ“Έ screenshots/21-assign-role.png β€” assigning the writer role/group in Keycloak] @@ -277,7 +300,7 @@ her to a **group** that carries it. The role travels inside her token to the End ## Log in -Ana opens the Endpoint web app and logs in with her AAI user. +The user opens the Endpoint web app and logs in with their AAI user. The home page is the **search**: the heart of the Endpoint. @@ -287,8 +310,8 @@ The home page is the **search**: the heart of the Endpoint. ## Create an organization -From the **"+ New" β†’ Organization** menu, Ana creates the organization that will -group her data. +From the **"+ New" β†’ Organization** menu, the user creates the organization that +will group their data. [πŸ“Έ screenshots/31-create-organization.png β€” new organization form] @@ -296,7 +319,7 @@ group her data. ## Publish a dataset -**"+ New" β†’ Dataset**: Ana describes her dataset (title, description, tags…). +**"+ New" β†’ Dataset**: the user describes the dataset (title, description, tags…). [πŸ“Έ screenshots/32-create-dataset.png β€” new dataset form] @@ -316,8 +339,8 @@ A dataset can have resources of several kinds, all from **"+ New"**: ## Search and find -Ana (or anyone) searches by text, filters, and finds the just-published dataset. -On her own data, the **publish/delete** actions appear. +Anyone can search by text, filter, and find the just-published dataset. +On your own data, the **publish/delete** actions appear. [πŸ“Έ screenshots/34-search-results.png β€” search results with the dataset] @@ -484,7 +507,7 @@ public ports. ## Summary 1. We **installed** NDP from scratch (Docker). -2. Ana **logged in** and received her **role** (both in AAI). +2. The user **logged in** and received a **role** (both in AAI). 3. She **published and searched** data from the Endpoint **web app**. 4. She did the same **from code** with the Python library. 5. The data was **federated** and is discovered elsewhere. From 5fb0ca2ff02062105f712f2e6b72c65513390504 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Wed, 27 May 2026 12:35:57 -0600 Subject: [PATCH 13/67] docs(demo): remove remaining gendered pronouns in narrative Refs #179 --- docs/demo/NDP-demo-presentation.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index de971e9..f6bad51 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -266,7 +266,7 @@ In the Keycloak console, the administrator creates the **user** and sets a passw [πŸ“Έ screenshots/20-create-user.png β€” creating a user in Keycloak] -> The user alone **cannot publish anything yet**: she needs a **role**. +> The user alone **cannot publish anything yet**: they need a **role**. --- @@ -506,10 +506,10 @@ public ports. ## Summary -1. We **installed** NDP from scratch (Docker). +1. We **installed** the NDP-EP (Docker). 2. The user **logged in** and received a **role** (both in AAI). -3. She **published and searched** data from the Endpoint **web app**. -4. She did the same **from code** with the Python library. +3. They **published and searched** data from the Endpoint **web app**. +4. They did the same **from code** with the Python library. 5. The data was **federated** and is discovered elsewhere. 6. Everything can run over a **secure network** (NetBird). From 3477542c3a32b79ceaafeabf9f0d0481a3a4b358 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Wed, 27 May 2026 12:46:29 -0600 Subject: [PATCH 14/67] docs(demo): rename section dividers from 'Act' to 'Step' Refs #179 --- docs/demo/NDP-demo-presentation.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index f6bad51..078f638 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -109,7 +109,7 @@ registry the EP writes into; it is non-blocking (the EP works even if it is down > A new user gets access, publishes a dataset, automates it from code, and that > data shows up in the federation β€” all securely. -**Demo acts:** +**Steps:** 1. Installation 2. Identity and permissions (sign in and get a role) 3. The Endpoint in action (publish and search from the web) @@ -119,7 +119,7 @@ registry the EP writes into; it is non-blocking (the EP works even if it is down --- -# Act 1 β€” Installation +# Step 1 β€” Installation --- @@ -134,7 +134,7 @@ already provides identity (**AAI**), **Affinities** and **Federation**. Run *everything* on your own machine, with no dependency on the central NDP. β†’ you install **all** components. -> Next slide: the common case. The rest of Act 1: the full stack. +> Next slide: the common case. The rest of Step 1: the full stack. --- @@ -251,11 +251,11 @@ From here on we work **from the web** (and later from code). [πŸ“Έ screenshots/15-docker-ps.png β€” list of containers in Up state] - + --- -# Act 2 β€” Identity and permissions +# Step 2 β€” Identity and permissions ### A user signs in and gets a role --- @@ -289,11 +289,11 @@ adding them to a **group** that carries it. The role travels inside the token to > With no role assigned, a user can only see public data. **Secure by default.** - + --- -# Act 3 β€” The Endpoint in action +# Step 3 β€” The Endpoint in action ### Publish and search from the web --- @@ -369,7 +369,7 @@ It is a storage administration tool: **writers/admins only**. --- -# Act 4 β€” Automate with Python +# Step 4 β€” Automate with Python ### The same thing, from code + --- From c41e2ad16473be4bec24daa0e2de48f7ac8daa41 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Wed, 27 May 2026 13:08:01 -0600 Subject: [PATCH 18/67] docs(demo): hide screenshot placeholders; link .env reference on install slide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Convert all [πŸ“Έ ...] markers to hidden HTML comments so they no longer render as literal text on slides (they remain as a guide; the README keeps the capture checklist). - Add a visible pointer to docs/configuration.md on the install slide. - Restore blank lines before slide separators after the conversion. Refs #179 --- docs/demo/NDP-demo-presentation.md | 47 ++++++++++++++---------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index 7f888b4..1e2e1a7 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -150,7 +150,9 @@ cp example.env .env # configure your deployment (see next slide) docker compose up -d # add --profile mongodb to also start a local DB ``` -[πŸ“Έ screenshots/14-ep-home.png β€” Endpoint home page (search)] +> πŸ“– Every `.env` variable is explained in **`docs/configuration.md`** (template: `example.env`). + + --- @@ -202,8 +204,8 @@ docker compose up -d **What you will see:** the Keycloak admin console and the NDP login screen. -[πŸ“Έ screenshots/10-keycloak-login.png β€” NDP "Welcome back" login screen] -[πŸ“Έ screenshots/11-keycloak-admin.png β€” Keycloak admin console (realm NDP)] + + --- @@ -219,7 +221,7 @@ docker compose up -d - **Affinities web app**: `http://localhost:3000` - Database admin (pgAdmin): `http://localhost:5050` -[πŸ“Έ screenshots/12-affinities-frontend.png β€” Affinities web app (relationships graph)] + --- @@ -234,7 +236,7 @@ docker compose up -d - Web: `http://localhost:8020/ui/` - API & docs: `http://localhost:8020/docs` -[πŸ“Έ screenshots/13-federation-ui.png β€” federation web app (EP list, still empty)] + --- @@ -261,8 +263,7 @@ docker ps # all containers "Up / healthy" From here on we work **from the web** (and later from code). -[πŸ“Έ screenshots/15-docker-ps.png β€” list of containers in Up state] - + --- @@ -276,8 +277,7 @@ From here on we work **from the web** (and later from code). In the Keycloak console, the administrator creates the **user** and sets a password. -[πŸ“Έ screenshots/20-create-user.png β€” creating a user in Keycloak] - + > The user alone **cannot publish anything yet**: they need a **role**. --- @@ -287,7 +287,7 @@ In the Keycloak console, the administrator creates the **user** and sets a passw In **AAI** (Keycloak), the administrator gives the user a **role** β€” directly or by adding them to a **group** that carries it. The role travels inside the token to the Endpoint. -[πŸ“Έ screenshots/21-assign-role.png β€” assigning the writer role/group in Keycloak] + --- @@ -316,7 +316,7 @@ The user opens the Endpoint web app and logs in with their AAI user. The home page is the **search**: the heart of the Endpoint. -[πŸ“Έ screenshots/30-login-and-search.png β€” login + search page] + --- @@ -325,7 +325,7 @@ The home page is the **search**: the heart of the Endpoint. From the **"+ New" β†’ Organization** menu, the user creates the organization that will group their data. -[πŸ“Έ screenshots/31-create-organization.png β€” new organization form] + --- @@ -333,7 +333,7 @@ will group their data. **"+ New" β†’ Dataset**: the user describes the dataset (title, description, tags…). -[πŸ“Έ screenshots/32-create-dataset.png β€” new dataset form] + --- @@ -345,7 +345,7 @@ A dataset can have resources of several kinds, all from **"+ New"**: - **S3** β€” an object in S3-style storage - **Kafka** β€” a streaming data flow -[πŸ“Έ screenshots/33-create-resource.png β€” creating a resource (S3/URL/Kafka)] + --- @@ -354,7 +354,7 @@ A dataset can have resources of several kinds, all from **"+ New"**: Anyone can search by text, filter, and find the just-published dataset. On your own data, the **publish/delete** actions appear. -[πŸ“Έ screenshots/34-search-results.png β€” search results with the dataset] + --- @@ -366,8 +366,7 @@ The same web app **looks different depending on your role**: - ✏️ A **writer** does see **"+ New"** and **"S3 Management"** (bucket/object management). - πŸ› οΈ An **admin** also sees the **Dashboard** and the **access requests**. -[πŸ“Έ screenshots/35-viewer-vs-writer.png β€” menu comparison: viewer vs writer] - + --- @@ -377,7 +376,7 @@ The same web app **looks different depending on your role**: **S3 Management** lets you create and manage buckets and objects. It is a storage administration tool: **writers/admins only**. -[πŸ“Έ screenshots/36-s3-management.png β€” S3 Management tool (buckets/objects)] + --- @@ -418,8 +417,7 @@ client.create_dataset(name="measurements-2026", owner_org="my-org") print(client.search_datasets("measurements")) ``` -[πŸ“Έ screenshots/40-notebook.png β€” Jupyter notebook running these steps] - + --- @@ -446,7 +444,7 @@ print(client.search_datasets("measurements")) Each Endpoint registers with **Federation**. From then on, the central registry knows it exists and watches its **status** and **metrics**. -[πŸ“Έ screenshots/50-federation-ep-registered.png β€” the EP appears in the federation] + --- @@ -455,7 +453,7 @@ knows it exists and watches its **status** and **metrics**. The federation web app shows which Endpoints are **alive**, since when, and with what activity. -[πŸ“Έ screenshots/51-federation-health.png β€” EP health/metrics panel] + --- @@ -496,7 +494,7 @@ How do they talk **without** opening ports to the world? - You decide **who talks to whom**; everything else is blocked. - **No public ports** for the services. -[πŸ“Έ screenshots/60-netbird-peers.png β€” NetBird dashboard with connected machines (peers)] + --- @@ -506,8 +504,7 @@ Two machines on the network: one **reaches all the NDP services** of the other (EP, Federation, Affinities, AAI…) **only over the encrypted tunnel**, with no public ports. -[πŸ“Έ screenshots/61-netbird-access.png β€” proof of access to the services over the mesh] - + > This is exactly the production multi-machine scenario, already validated. --- From 36296a617c61fb223a4b9ba7308f009d5021f711 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Wed, 27 May 2026 13:08:55 -0600 Subject: [PATCH 19/67] docs(demo): reword .env reference to '.env variables are ...' Refs #179 --- docs/demo/NDP-demo-presentation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index 1e2e1a7..909d6a7 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -150,7 +150,7 @@ cp example.env .env # configure your deployment (see next slide) docker compose up -d # add --profile mongodb to also start a local DB ``` -> πŸ“– Every `.env` variable is explained in **`docs/configuration.md`** (template: `example.env`). +> πŸ“– `.env` variables are explained in **`docs/configuration.md`** (template: `example.env`). @@ -161,7 +161,7 @@ docker compose up -d # add --profile mongodb to also start a local DB - You run the **Endpoint** (API + web UI); its **catalog DB** and **object storage** are configured in `.env`. - **AAI Β· Affinities Β· Federation** are the platform's **shared services** β€” already running. -> πŸ“– Every `.env` variable is documented in **`docs/configuration.md`** +> πŸ“– `.env` variables are documented in **`docs/configuration.md`** > (template: `example.env`). --- -## What you run, what's shared +## What you operate vs. what the platform provides -- You run the **Endpoint** (API + web UI); its **catalog DB** and **object storage** are configured in `.env`. -- **AAI Β· Affinities Β· Federation** are the platform's **shared services** β€” already running. - -> πŸ“– `.env` variables are documented in **`docs/configuration.md`** -> (template: `example.env`). +| πŸ› οΈ You operate (your Endpoint) | ☁️ Shared by the platform | +|---|---| +| **NDP-EP** β€” API + web UI | **AAI** β€” identity & roles | +| **Catalog database** β€” CKAN or MongoDB | **Affinities** β€” relationship registry | +| **Object storage** β€” MinIO / S3 *(optional)* | **Federation** β€” registry & discovery | - +Your `.env` tells the Endpoint **how to reach** the shared services β€” so you run a +small footprint and the platform does the heavy lifting. + --- From d2d1c7d773ec25043fc4486f13b21fc0f9ff3f82 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Thu, 28 May 2026 06:51:33 -0600 Subject: [PATCH 22/67] docs(demo): fix AAI install steps (git clone, .env_template, SSL certs) The AAI repo uses .env_template (not .env.example) and needs a TLS cert step; add the git clone and --build per its README. Refs #179 --- docs/demo/NDP-demo-presentation.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index dcde577..2b6b919 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -163,8 +163,6 @@ docker compose up -d # add --profile mongodb to also start a local DB | **Catalog database** β€” CKAN or MongoDB | **Affinities** β€” relationship registry | | **Object storage** β€” MinIO / S3 *(optional)* | **Federation** β€” registry & discovery | -Your `.env` tells the Endpoint **how to reach** the shared services β€” so you run a -small footprint and the platform does the heavy lifting. @@ -198,9 +196,11 @@ Each component starts the same way: enter its folder and `docker compose up -d`. ## 1) Start AAI (identity) ```bash -cd ndp-keycloak-aai-old -cp .env.example .env # set admin user/password -docker compose up -d +git clone https://github.com/sci-ndp/ndp-keycloak-aai.git +cd ndp-keycloak-aai +cp .env_template .env # set admin user/password + domain +# place fullchain.pem & privkey.pem in SSL/certificates/ (TLS) +docker compose up -d --build ``` **What you will see:** the Keycloak admin console and the NDP login screen. From d165788b330ea119ca43ffcb3801be85235664ec Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Thu, 28 May 2026 06:53:21 -0600 Subject: [PATCH 23/67] docs(demo): add git clone + correct env templates to full-stack steps AAI uses the -old repo and .env_template; Affinities and Federation use .env.example. Add the git clone step to each (verified against their repos and READMEs). Refs #179 --- docs/demo/NDP-demo-presentation.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index 2b6b919..bfd2140 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -196,8 +196,8 @@ Each component starts the same way: enter its folder and `docker compose up -d`. ## 1) Start AAI (identity) ```bash -git clone https://github.com/sci-ndp/ndp-keycloak-aai.git -cd ndp-keycloak-aai +git clone https://github.com/sci-ndp/ndp-keycloak-aai-old.git +cd ndp-keycloak-aai-old cp .env_template .env # set admin user/password + domain # place fullchain.pem & privkey.pem in SSL/certificates/ (TLS) docker compose up -d --build @@ -213,7 +213,9 @@ docker compose up -d --build ## 2) Start Affinities (relationship registry) ```bash +git clone https://github.com/sci-ndp/ndp-affinities.git cd ndp-affinities +cp .env.example .env # optional: customize DB user/password docker compose up -d ``` @@ -229,7 +231,9 @@ docker compose up -d ## 3) Start Federation (central registry) ```bash +git clone https://github.com/sci-ndp/ndp-federation.git cd ndp-federation +cp .env.example .env # set ADMIN_PASSWORD docker compose up -d ``` From 3bfa73aae63ec11a0988c5a3d1f7c92942d6bb71 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Thu, 28 May 2026 06:55:37 -0600 Subject: [PATCH 24/67] docs(demo): don't repeat NDP-EP install in full-stack step 4 Reference the common-case install and only show the difference (point .env at local services; bring up backends with a Compose profile). Refs #179 --- docs/demo/NDP-demo-presentation.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index bfd2140..7e9fcdd 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -247,16 +247,15 @@ docker compose up -d ## 4) Start the NDP-EP (+ backends) +Install it exactly like the **common case** shown earlier β€” the only difference is +the `.env`: point it to your **local** AAI Β· Affinities Β· Federation, and bring up +the data backends with a Compose profile. + ```bash -cd ep-api -cp .env.example .env # point to your LOCAL AAI, Affinities, Federation -docker compose up -d +docker compose --profile full up -d # Endpoint + MongoDB + MinIO + Kafka ``` -Starts the Endpoint alongside its backends: **CKAN**, **MongoDB** and **MinIO** (S3). - -**What you will see:** the same Endpoint web app as before, now wired to your -local services β€” `…/ep-api/ui/` and API docs at `…/ep-api/docs`. +**What you will see:** the Endpoint web app at `…/ep-api/ui/`, now wired to your local stack. --- From e9c7ee3a5968ccbae5f5f74bdb34e778e720d1e5 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Thu, 28 May 2026 06:56:32 -0600 Subject: [PATCH 25/67] docs(demo): tighten full-stack step 4 wording Refs #179 --- docs/demo/NDP-demo-presentation.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index 7e9fcdd..2fa2910 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -247,9 +247,9 @@ docker compose up -d ## 4) Start the NDP-EP (+ backends) -Install it exactly like the **common case** shown earlier β€” the only difference is -the `.env`: point it to your **local** AAI Β· Affinities Β· Federation, and bring up -the data backends with a Compose profile. +Identical to the common-case install. Configure `.env` to reference the local +AAI, Affinities and Federation instances, and start the data backends with a +Compose profile. ```bash docker compose --profile full up -d # Endpoint + MongoDB + MinIO + Kafka From d0f820a8767d9b913723898d73155a2166700d26 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Thu, 28 May 2026 06:58:43 -0600 Subject: [PATCH 26/67] docs(demo): explain Compose profiles on the NDP-EP install slide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clarify that 'docker compose up -d' starts only the Endpoint, and that optional local backends (mongodb, s3, kafka, jupyter, full) are added via Compose profiles β€” so users can run only the EP or the full set. Refs #179 --- docs/demo/NDP-demo-presentation.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index 2fa2910..2de4eae 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -147,9 +147,12 @@ Run *everything* on your own machine, with no dependency on the central NDP. git clone https://github.com/national-data-platform/ep-api.git cd ep-api cp example.env .env # configure your deployment (see next slide) -docker compose up -d # add --profile mongodb to also start a local DB +docker compose up -d # the Endpoint only ``` +**Optional local backends** β€” add Compose profiles to run them too: +`--profile mongodb` (DB) Β· `s3` (MinIO) Β· `kafka` Β· `jupyter` Β· `full` (all). + > πŸ“– `.env` variables are explained in **`docs/configuration.md`** (template: `example.env`). From 9ffac3d30126d0926f893cab5c2b371c768a8e8c Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Thu, 28 May 2026 07:00:36 -0600 Subject: [PATCH 27/67] docs(demo): add Compose profiles slide explaining what each one starts New slide tabulates each profile and the exact services it brings up (none = EP only; mongodb, s3, kafka, jupyter, pelican, full), so users can run only the Endpoint or any subset of local backends. Install slide points to it. Refs #179 --- docs/demo/NDP-demo-presentation.md | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index 2de4eae..21e65e6 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -150,11 +150,28 @@ cp example.env .env # configure your deployment (see next slide) docker compose up -d # the Endpoint only ``` -**Optional local backends** β€” add Compose profiles to run them too: -`--profile mongodb` (DB) Β· `s3` (MinIO) Β· `kafka` Β· `jupyter` Β· `full` (all). +> Run only the Endpoint, or add local backends with **Compose profiles** (next slide). > πŸ“– `.env` variables are explained in **`docs/configuration.md`** (template: `example.env`). +--- + +## Optional backends β€” Compose profiles + +`docker compose --profile up -d` β€” combine as many as you need: + +| Profile | What it starts | +|---|---| +| *(none)* | **NDP-EP only** (API + web UI) | +| `mongodb` | MongoDB + Mongo Express (local catalog DB) | +| `s3` | MinIO (S3-compatible object storage) | +| `kafka` | Kafka + Zookeeper + Kafka UI (streaming) | +| `jupyter` | JupyterLab | +| `pelican` | Pelican federation (registry, director, origin, cache) | +| `full` | All of the above | + + --- From b0c569855fd810087e5b0f34c86cc76140373e47 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Thu, 28 May 2026 07:02:32 -0600 Subject: [PATCH 28/67] docs(demo): split Compose profiles table across two slides Refs #179 --- docs/demo/NDP-demo-presentation.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index 21e65e6..e5fe76c 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -156,7 +156,7 @@ docker compose up -d # the Endpoint only --- -## Optional backends β€” Compose profiles +## Compose profiles β€” core backends `docker compose --profile up -d` β€” combine as many as you need: @@ -166,9 +166,16 @@ docker compose up -d # the Endpoint only | `mongodb` | MongoDB + Mongo Express (local catalog DB) | | `s3` | MinIO (S3-compatible object storage) | | `kafka` | Kafka + Zookeeper + Kafka UI (streaming) | + +--- + +## Compose profiles β€” extras + +| Profile | What it starts | +|---|---| | `jupyter` | JupyterLab | | `pelican` | Pelican federation (registry, director, origin, cache) | -| `full` | All of the above | +| `full` | All backends above | From 0574abf007a5c0b6597b05f0d6312496ff2a79ce Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Thu, 28 May 2026 07:05:31 -0600 Subject: [PATCH 29/67] docs(demo): note CKAN local catalog needs an accessible CKAN + admin token On the NDP-EP install slide, clarify that choosing CKAN as the local catalog requires a running/accessible CKAN and an admin API token (CKAN_API_KEY), whereas MongoDB needs none. Refs #179 --- docs/demo/NDP-demo-presentation.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index e5fe76c..9c74f3b 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -146,10 +146,12 @@ Run *everything* on your own machine, with no dependency on the central NDP. ```bash git clone https://github.com/national-data-platform/ep-api.git cd ep-api -cp example.env .env # configure your deployment (see next slide) +cp example.env .env # configure your deployment docker compose up -d # the Endpoint only ``` +> Using **CKAN** as local catalog? You need a running CKAN (your own or accessible) and an admin **API token** for `CKAN_API_KEY`. MongoDB needs none. + > Run only the Endpoint, or add local backends with **Compose profiles** (next slide). > πŸ“– `.env` variables are explained in **`docs/configuration.md`** (template: `example.env`). From 6234a12a3750938162ea0f321e05062c86fc1151 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Thu, 28 May 2026 07:07:49 -0600 Subject: [PATCH 30/67] docs(demo): professionalize CKAN backend prerequisite wording Refs #179 --- docs/demo/NDP-demo-presentation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index 9c74f3b..ad3926b 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -150,7 +150,7 @@ cp example.env .env # configure your deployment docker compose up -d # the Endpoint only ``` -> Using **CKAN** as local catalog? You need a running CKAN (your own or accessible) and an admin **API token** for `CKAN_API_KEY`. MongoDB needs none. +> The CKAN backend requires an existing, reachable CKAN instance and an administrator API token (`CKAN_API_KEY`). The MongoDB backend has no such prerequisite. > Run only the Endpoint, or add local backends with **Compose profiles** (next slide). From e48bdb06a8cf0885c5d2ac977d18c99dc27e04e9 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Thu, 28 May 2026 07:14:37 -0600 Subject: [PATCH 31/67] docs(demo): professional, technical tone across the deck Remove colloquial/rhetorical phrasing (kept emojis): rework the overview narrative, install options, role/permission descriptions, Python-library and NetBird sections, federation copy, summary and closing slide into a neutral, technical register. Refs #179 --- docs/demo/NDP-demo-presentation.md | 82 +++++++++++++++--------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index ad3926b..e6c8bb9 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -106,8 +106,8 @@ registry the EP writes into; it is non-blocking (the EP works even if it is down ## Overview -> A new user gets access, publishes a dataset, automates it from code, and that -> data shows up in the federation β€” all securely. +> A new user is granted access, publishes a dataset, performs the same tasks from +> code, and the dataset becomes discoverable across the federation β€” all securely. **Steps:** 1. Installation @@ -125,14 +125,14 @@ registry the EP writes into; it is non-blocking (the EP works even if it is down ## Two ways to install -**🟒 Most users β€” just the NDP-EP** +**🟒 Most users β€” the NDP-EP only** Run your own **Endpoint** and connect it to the **National Data Platform**, which already provides identity (**AAI**), **Affinities** and **Federation**. -β†’ you install **one** component. +β†’ install **one** component. **πŸ§ͺ Full stack β€” development / testing** -Run *everything* on your own machine, with no dependency on the central NDP. -β†’ you install **all** components. +Run all components locally, with no dependency on the central NDP. +β†’ install **all** components. > Next slide: the common case. The rest of Step 1: the full stack. @@ -294,7 +294,7 @@ docker compose --profile full up -d # Endpoint + MongoDB + MinIO + Kafka docker ps # all containers "Up / healthy" ``` -From here on we work **from the web** (and later from code). +Subsequent steps use the **web interface**, and later the Python library. @@ -347,7 +347,7 @@ adding them to a **group** that carries it. The role travels inside the token to The user opens the Endpoint web app and logs in with their AAI user. -The home page is the **search**: the heart of the Endpoint. +The home page is the **search** interface β€” the Endpoint's primary entry point. @@ -384,8 +384,8 @@ A dataset can have resources of several kinds, all from **"+ New"**: ## Search and find -Anyone can search by text, filter, and find the just-published dataset. -On your own data, the **publish/delete** actions appear. +Any user can search by text and filters and find the published dataset. +For datasets they own, **publish/delete** actions are available. @@ -393,11 +393,11 @@ On your own data, the **publish/delete** actions appear. ## Role-based access in practice πŸ”‘ -The same web app **looks different depending on your role**: +The interface adapts to the authenticated user's role: -- πŸ‘οΈ A **viewer** logs in, searches and looks β€” **does not see** "S3 Management" or "+ New". -- ✏️ A **writer** does see **"+ New"** and **"S3 Management"** (bucket/object management). -- πŸ› οΈ An **admin** also sees the **Dashboard** and the **access requests**. +- πŸ‘οΈ **Viewer** β€” can browse and search; **does not see** "S3 Management" or "+ New". +- ✏️ **Writer** β€” additionally sees **"+ New"** and **"S3 Management"** (bucket/object management). +- πŸ› οΈ **Admin** β€” additionally sees the **Dashboard** and **access requests**. @@ -406,15 +406,15 @@ The same web app **looks different depending on your role**: ## Storage management (S3) β€” writers only -**S3 Management** lets you create and manage buckets and objects. -It is a storage administration tool: **writers/admins only**. +**S3 Management** creates and manages buckets and objects. +It is a storage administration tool, restricted to **writers and admins**. --- # Step 4 β€” Automate with Python -### The same thing, from code +### The same operations, from code @@ -423,14 +423,14 @@ everything in the web can also be automated". --> ## The `ndp-ep` library -Everything you do in the web app can also be done **from code**, ideal for -automating or bulk-loading data. +Every web-app operation is also available **from code** β€” suitable for automation +and bulk loading. ```bash pip install ndp-ep ``` -> Useful for researchers and teams loading data repeatedly. +> Intended for researchers and teams that load data programmatically. --- @@ -463,7 +463,7 @@ print(client.search_datasets("measurements")) Python (code) β”€β”˜ ``` -> Web for day-to-day, code to automate. **Same data, same permissions.** +> The web interface and the library target the same Endpoint: **identical data and permissions.** --- @@ -474,8 +474,8 @@ print(client.search_datasets("measurements")) ## The Endpoint registers -Each Endpoint registers with **Federation**. From then on, the central registry -knows it exists and watches its **status** and **metrics**. +Each Endpoint registers with **Federation**. The central registry then tracks its +**status** and **metrics**. @@ -483,8 +483,8 @@ knows it exists and watches its **status** and **metrics**. ## Health and metrics -The federation web app shows which Endpoints are **alive**, since when, and with -what activity. +The federation web app reports which Endpoints are **online**, since when, and +their activity. @@ -494,15 +494,15 @@ what activity. ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Federation β”‚ "the map of all the data" + β”‚ Federation β”‚ registry of all endpoints β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β–Ό β–Ό β–Ό [ EP Utah ] [ EP B ] [ EP C ] each institution, its catalog ``` -> You search in one place and find data from **many** institutions. -> Each one keeps control of **its** data. +> A single search surfaces data from **many** institutions, while each retains +> control of **its own** data. --- @@ -513,10 +513,10 @@ what activity. ## The problem -In production, each component lives on a **different machine**. -How do they talk **without** opening ports to the world? +In production, each component runs on a **different machine** and must communicate +**without** exposing public ports. -> Answer: a **private encrypted network** (mesh VPN) connecting only our machines. +> A **private, encrypted mesh VPN** connects only authorized machines. --- @@ -524,7 +524,7 @@ How do they talk **without** opening ports to the world? - Each machine gets a **stable private IP** on a virtual network. - Traffic goes **directly and encrypted** between machines (WireGuard). -- You decide **who talks to whom**; everything else is blocked. +- Access is restricted to **explicitly authorized peers**; all other traffic is blocked. - **No public ports** for the services. @@ -538,7 +538,7 @@ Two machines on the network: one **reaches all the NDP services** of the other public ports. -> This is exactly the production multi-machine scenario, already validated. +> This validates the production multi-machine scenario. --- @@ -548,12 +548,12 @@ public ports. ## Summary -1. We **installed** the NDP-EP (Docker). -2. The user **logged in** and received a **role** (both in AAI). -3. They **published and searched** data from the Endpoint **web app**. -4. They did the same **from code** with the Python library. -5. The data was **federated** and is discovered elsewhere. -6. Everything can run over a **secure network** (NetBird). +1. The **NDP-EP** was installed (Docker). +2. The user **authenticated** and received a **role** (both in AAI). +3. Datasets were **published and searched** from the **web app**. +4. The same operations were performed **from code** via the Python library. +5. The data was **federated** and became discoverable across the platform. +6. All components can run over a **secure network** (NetBird). > **Distributed data, unified discovery, governed and secure access.** @@ -569,7 +569,7 @@ public ports. --- -# Thank you! -## Questions +# Thank you +## Questions & discussion From 437a90f41f8cf3008f0b28dec2c9ed85ce838816 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Thu, 28 May 2026 07:19:12 -0600 Subject: [PATCH 32/67] docs(demo): add 'bootstrap the first admin' slide to Step 2 The Endpoint has no user store; admin is the Keycloak realm role ndp_admin (or group::admin). Explain that the first admin must be assigned directly in Keycloak (granting roles via the EP UI / AAI API requires an existing admin), and that in the common case the platform operators assign it. Refs #179 --- docs/demo/NDP-demo-presentation.md | 19 +++++++++++++++++++ docs/demo/README.md | 1 + 2 files changed, 20 insertions(+) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index e6c8bb9..3d580f1 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -306,6 +306,25 @@ Subsequent steps use the **web interface**, and later the Python library. --- +## Bootstrap the first admin + +The Endpoint has **no user store** β€” identity and roles come from **AAI (Keycloak)**. +The **first** admin must be set up directly in Keycloak, because granting roles from +the Endpoint UI or the AAI API itself requires an existing admin. + +In Keycloak (realm **NDP**): +1. Create the user and set a password. +2. Assign the realm role **`ndp_admin`** (platform-wide), or **`group::admin`** for this Endpoint only. + +That user can then sign in and manage everyone else from the Endpoint. + +> In the common case (central NDP), the admin role is assigned by the platform +> operators in the shared AAI β€” request it from them. + + + +--- + ## Create the user (AAI) In the Keycloak console, the administrator creates the **user** and sets a password. diff --git a/docs/demo/README.md b/docs/demo/README.md index daf42c0..71e5f12 100644 --- a/docs/demo/README.md +++ b/docs/demo/README.md @@ -43,6 +43,7 @@ screenshot. Checklist: - [ ] `15-docker-ps.png` β€” `docker ps` with everything "Up" **Identity and permissions** +- [ ] `19-keycloak-assign-ndp-admin.png` β€” assigning the `ndp_admin` realm role in Keycloak (first admin) - [ ] `20-create-user.png` β€” creating a user in Keycloak - [ ] `21-assign-role.png` β€” assigning the writer role/group in Keycloak (AAI) From e43e9807cbdec4aac6bf43a618b3e2d3ec94a8f3 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Thu, 28 May 2026 07:23:43 -0600 Subject: [PATCH 33/67] docs(demo): add prerequisites slide (incl. EP_UUID before install) Add a 'Before you install' slide listing what must be ready before .env configuration: AAI endpoint, catalog backend (MongoDB or CKAN + token), EP_UUID (obtained by registering the EP in Affinities; required for Affinities/per-EP roles), and optional object storage. Refs #179 --- docs/demo/NDP-demo-presentation.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index 3d580f1..b4d59a2 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -134,7 +134,21 @@ already provides identity (**AAI**), **Affinities** and **Federation**. Run all components locally, with no dependency on the central NDP. β†’ install **all** components. -> Next slide: the common case. The rest of Step 1: the full stack. +> The common case is covered first; the full stack follows. + +--- + +## Before you install β€” prerequisites + +Have these ready; the installer writes them into `.env`: + +- **AAI endpoint** β€” the AAI `…/information` URL, so logins and roles work. +- **Catalog backend** β€” a MongoDB (Compose can start it) **or** a reachable **CKAN** instance with an admin **API token**. +- **EP_UUID** β€” required only when using Affinities or per-EP roles (`group::…`). Register this Endpoint in Affinities (`POST /endpoints`) and use the returned `uid` as `AFFINITIES_EP_UUID`. +- **Object storage** β€” optional, only for S3 features. + +> In the common case, the platform operators provide the AAI endpoint and, if +> applicable, the `EP_UUID`. --- From 733a8d0384c0187b16ad051fc2f3c9f7ff053830 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Thu, 28 May 2026 07:30:39 -0600 Subject: [PATCH 34/67] docs: add appendix on obtaining EP_UUID; correct Affinities path to /ep Add an appendix slide showing both ways to get the EP_UUID (Affinities web app Endpoints page, or GET/POST /ep on the API). Correct the Affinities endpoint path from /endpoints to the real /ep in the prerequisites slide and in configuration.md. Refs #179 --- docs/configuration.md | 5 +++-- docs/demo/NDP-demo-presentation.md | 29 ++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 4157709..dc22bcf 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -218,8 +218,9 @@ platform's Affinities URL, or your local one. #### `AFFINITIES_EP_UUID` *Required if `AFFINITIES_ENABLED=True`.* -This Endpoint's UUID inside Affinities. **Where:** register the Endpoint once via -`POST /endpoints` on the Affinities API; the response's `uid` is this value. See +This Endpoint's UUID inside Affinities. **Where:** the endpoint's `uid` in +Affinities β€” list/create it via `GET`/`POST /ep` on the Affinities API, or from +the **Endpoints** page of the Affinities web app. See [affinities-integration.md](affinities-integration.md). #### `AFFINITIES_TIMEOUT` diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index b4d59a2..a5c2dba 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -144,7 +144,7 @@ Have these ready; the installer writes them into `.env`: - **AAI endpoint** β€” the AAI `…/information` URL, so logins and roles work. - **Catalog backend** β€” a MongoDB (Compose can start it) **or** a reachable **CKAN** instance with an admin **API token**. -- **EP_UUID** β€” required only when using Affinities or per-EP roles (`group::…`). Register this Endpoint in Affinities (`POST /endpoints`) and use the returned `uid` as `AFFINITIES_EP_UUID`. +- **EP_UUID** β€” required only when using Affinities or per-EP roles (`group::…`). It is the Endpoint's `uid` in Affinities (`POST /ep`, or the **Endpoints** page of the Affinities UI). See the appendix. Used as `AFFINITIES_EP_UUID`. - **Object storage** β€” optional, only for S3 features. > In the common case, the platform operators provide the AAI endpoint and, if @@ -606,3 +606,30 @@ public ports. ## Questions & discussion + +--- + +# Appendix + +--- + +## Obtaining the EP_UUID + +The `EP_UUID` is this Endpoint's `uid` in **Affinities**. Two ways to obtain it: + +**Affinities web app** (`http://localhost:3000`, or your Affinities URL) +Open the **Endpoints** page β€” the **UID** column shows each endpoint's `uid`. +Create the endpoint there if it does not exist yet. + +**Affinities API** (`http://localhost:8000`, Swagger at `/docs`) + +```bash +# list endpoints and copy your uid +curl http://localhost:8000/ep + +# or register this endpoint; the response includes "uid" +curl -X POST http://localhost:8000/ep -H 'Content-Type: application/json' \ + -d '{"kind":"ndp-ep","url":"https://","metadata":{"name":"My EP"}}' +``` + +Use the returned `uid` as `AFFINITIES_EP_UUID` in `.env` and in `group::…` roles. From 79e903181ee860f8ed156492667f3d6719a666bb Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Thu, 28 May 2026 07:35:59 -0600 Subject: [PATCH 35/67] docs(demo): split EP_UUID appendix into two slides and cross-reference it Split 'Obtaining the EP_UUID' into web-app and API slides, and reference the appendix from where the value is requested (prerequisites and the admin bootstrap slide). Refs #179 --- docs/demo/NDP-demo-presentation.md | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index a5c2dba..a2c5c87 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -144,7 +144,7 @@ Have these ready; the installer writes them into `.env`: - **AAI endpoint** β€” the AAI `…/information` URL, so logins and roles work. - **Catalog backend** β€” a MongoDB (Compose can start it) **or** a reachable **CKAN** instance with an admin **API token**. -- **EP_UUID** β€” required only when using Affinities or per-EP roles (`group::…`). It is the Endpoint's `uid` in Affinities (`POST /ep`, or the **Endpoints** page of the Affinities UI). See the appendix. Used as `AFFINITIES_EP_UUID`. +- **EP_UUID** β€” required only when using Affinities or per-EP roles (`group::…`). It is the Endpoint's `uid` in Affinities, used as `AFFINITIES_EP_UUID`. β†’ see appendix *Obtaining the EP_UUID*. - **Object storage** β€” optional, only for S3 features. > In the common case, the platform operators provide the AAI endpoint and, if @@ -328,7 +328,7 @@ the Endpoint UI or the AAI API itself requires an existing admin. In Keycloak (realm **NDP**): 1. Create the user and set a password. -2. Assign the realm role **`ndp_admin`** (platform-wide), or **`group::admin`** for this Endpoint only. +2. Assign the realm role **`ndp_admin`** (platform-wide), or **`group::admin`** for this Endpoint only (`EP_UUID` β†’ see appendix *Obtaining the EP_UUID*). That user can then sign in and manage everyone else from the Endpoint. @@ -613,15 +613,23 @@ public ports. --- -## Obtaining the EP_UUID +## Obtaining the EP_UUID β€” Affinities web app -The `EP_UUID` is this Endpoint's `uid` in **Affinities**. Two ways to obtain it: +The `EP_UUID` is this Endpoint's `uid` in **Affinities**. -**Affinities web app** (`http://localhost:3000`, or your Affinities URL) -Open the **Endpoints** page β€” the **UID** column shows each endpoint's `uid`. -Create the endpoint there if it does not exist yet. +**Via the Affinities web app** (`http://localhost:3000`, or your Affinities URL): -**Affinities API** (`http://localhost:8000`, Swagger at `/docs`) +1. Open the **Endpoints** page. +2. Copy the value in the **UID** column for your endpoint. +3. If it does not exist yet, create it there first. + +Use that `uid` as `AFFINITIES_EP_UUID` in `.env` (and in `group::…` roles). + +--- + +## Obtaining the EP_UUID β€” Affinities API + +**Via the Affinities API** (`http://localhost:8000`, Swagger at `/docs`): ```bash # list endpoints and copy your uid @@ -632,4 +640,4 @@ curl -X POST http://localhost:8000/ep -H 'Content-Type: application/json' \ -d '{"kind":"ndp-ep","url":"https://","metadata":{"name":"My EP"}}' ``` -Use the returned `uid` as `AFFINITIES_EP_UUID` in `.env` and in `group::…` roles. +The returned `uid` is your `AFFINITIES_EP_UUID`. From e5c573d420d75284f2a7b2b87a0267a79b43b545 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Thu, 28 May 2026 07:39:57 -0600 Subject: [PATCH 36/67] docs(demo): EP_UUID web-app slide follows the Add Endpoint flow + embed image Reword the web-app appendix slide to match the UI (Endpoints -> Add Endpoint -> form -> Save) and embed screenshots/A1-affinities-add-endpoint.png. Add it to the screenshot checklist. Refs #179 --- docs/demo/NDP-demo-presentation.md | 12 ++++-------- docs/demo/README.md | 3 +++ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index a2c5c87..2d80212 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -615,15 +615,11 @@ public ports. ## Obtaining the EP_UUID β€” Affinities web app -The `EP_UUID` is this Endpoint's `uid` in **Affinities**. +In the Affinities web app (`http://localhost:3000`, or your Affinities URL): +**Endpoints β†’ Add Endpoint**, fill the form (**Kind** = `ndp-ep`, **URL**, optional +**Metadata**), then **Save**. The new row's **UID** is your `AFFINITIES_EP_UUID`. -**Via the Affinities web app** (`http://localhost:3000`, or your Affinities URL): - -1. Open the **Endpoints** page. -2. Copy the value in the **UID** column for your endpoint. -3. If it does not exist yet, create it there first. - -Use that `uid` as `AFFINITIES_EP_UUID` in `.env` (and in `group::…` roles). +![w:760](screenshots/A1-affinities-add-endpoint.png) --- diff --git a/docs/demo/README.md b/docs/demo/README.md index 71e5f12..4e09922 100644 --- a/docs/demo/README.md +++ b/docs/demo/README.md @@ -67,6 +67,9 @@ screenshot. Checklist: - [ ] `60-netbird-peers.png` β€” dashboard with connected peers - [ ] `61-netbird-access.png` β€” accessing services over the mesh +**Appendix** +- [ ] `A1-affinities-add-endpoint.png` β€” Affinities "Add Endpoint" form (obtaining the EP_UUID) + ## Notes - Presentation text (and speaker notes ``) are in **English**. From 0ed5e439f94b0497a3369a5fa8c26d19ad5610a8 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Thu, 28 May 2026 09:20:40 -0600 Subject: [PATCH 37/67] docs(demo): constrain EP_UUID screenshot by height so it fits the slide Refs #179 --- docs/demo/NDP-demo-presentation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index 2d80212..f6c149e 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -619,7 +619,7 @@ In the Affinities web app (`http://localhost:3000`, or your Affinities URL): **Endpoints β†’ Add Endpoint**, fill the form (**Kind** = `ndp-ep`, **URL**, optional **Metadata**), then **Save**. The new row's **UID** is your `AFFINITIES_EP_UUID`. -![w:760](screenshots/A1-affinities-add-endpoint.png) +![h:300](screenshots/A1-affinities-add-endpoint.png) --- From 3160739fefe19bf27d1377a11708be2927943660 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Thu, 28 May 2026 09:24:08 -0600 Subject: [PATCH 38/67] docs(demo): split 'Bootstrap the first admin' into two slides Refs #179 --- docs/demo/NDP-demo-presentation.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index f6c149e..92679cc 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -323,18 +323,24 @@ Subsequent steps use the **web interface**, and later the Python library. ## Bootstrap the first admin The Endpoint has **no user store** β€” identity and roles come from **AAI (Keycloak)**. -The **first** admin must be set up directly in Keycloak, because granting roles from -the Endpoint UI or the AAI API itself requires an existing admin. + +The **first** admin must be set up **directly in Keycloak**, because granting roles +from the Endpoint UI or the AAI API itself requires an existing admin. + +> In the common case (central NDP), the admin role is assigned by the platform +> operators in the shared AAI β€” request it from them. + +--- + +## Bootstrap the first admin β€” steps In Keycloak (realm **NDP**): + 1. Create the user and set a password. 2. Assign the realm role **`ndp_admin`** (platform-wide), or **`group::admin`** for this Endpoint only (`EP_UUID` β†’ see appendix *Obtaining the EP_UUID*). That user can then sign in and manage everyone else from the Endpoint. -> In the common case (central NDP), the admin role is assigned by the platform -> operators in the shared AAI β€” request it from them. - --- From 31e6f0d2d51aaeea6b83fb14aee0a5e469ffcfcb Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Thu, 28 May 2026 09:29:16 -0600 Subject: [PATCH 39/67] =?UTF-8?q?docs(demo):=20appendix=20=E2=80=94=20Keyc?= =?UTF-8?q?loak=20for=20user+password,=20AAI=20API=20for=20groups/roles?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Group/role assignment is done via the AAI API (caller must already be an admin); only user creation + password is done in Keycloak. Replace the Keycloak 'assign role' appendix slide with an AAI API slide, and document the first-admin exception (ndp_admin must be set directly in Keycloak because no admin exists yet to call the API). Refs #179 --- docs/demo/NDP-demo-presentation.md | 36 ++++++++++++++++++++++++++++++ docs/demo/README.md | 1 + 2 files changed, 37 insertions(+) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index 92679cc..572e54c 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -643,3 +643,39 @@ curl -X POST http://localhost:8000/ep -H 'Content-Type: application/json' \ ``` The returned `uid` is your `AFFINITIES_EP_UUID`. + +--- + +## Appendix β€” Keycloak: create the first user + +In the Keycloak admin console, realm **NDP**: + +1. **Users β†’ Add user** β€” set **Username** and the required profile fields (email, first/last name), then **Create**. +2. Open the user β†’ **Credentials β†’ Set password** β€” turn **Temporary** off, then **Save**. + +![h:280](screenshots/A2-keycloak-create-user.png) + +--- + +## Appendix β€” AAI API: assign groups & roles + +After the user exists in Keycloak, assign groups/roles via the **AAI API** +(the caller must already be an admin): + +```bash +TOKEN=$(curl -s -X POST "$AAI/user/login" -H 'Content-Type: application/json' \ + -d '{"username":"","password":""}' | jq -r .access_token) + +# join the EP group (assigned the viewer role automatically) +curl -s -X POST "$AAI/group/add-user" -H "Authorization: Bearer $TOKEN" \ + -H 'Content-Type: application/json' \ + -d '{"group_name":"","username":""}' + +# upgrade the tier (bare name: viewer | writer | admin) +curl -s -X POST "$AAI/role/assign" -H "Authorization: Bearer $TOKEN" \ + -H 'Content-Type: application/json' \ + -d '{"groupName":"","roleName":"writer","username":""}' +``` + +> **First admin exception:** assign `ndp_admin` **directly in Keycloak** β€” no admin +> exists yet to call this API. The user must re-login for new roles to take effect. diff --git a/docs/demo/README.md b/docs/demo/README.md index 4e09922..ed02851 100644 --- a/docs/demo/README.md +++ b/docs/demo/README.md @@ -69,6 +69,7 @@ screenshot. Checklist: **Appendix** - [ ] `A1-affinities-add-endpoint.png` β€” Affinities "Add Endpoint" form (obtaining the EP_UUID) +- [ ] `A2-keycloak-create-user.png` β€” Keycloak: create user + set password (bootstrap) ## Notes From 34c40a06ee1f3e4b77e8681215acb0e635dc1246 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Thu, 28 May 2026 09:32:20 -0600 Subject: [PATCH 40/67] docs(demo): unify appendix slide titles and split the AAI API slide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use a consistent ' β€” ' title style across appendix slides and split the AAI API group/role assignment across two slides so it fits. Refs #179 --- docs/demo/NDP-demo-presentation.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index 572e54c..0bd77e1 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -646,7 +646,7 @@ The returned `uid` is your `AFFINITIES_EP_UUID`. --- -## Appendix β€” Keycloak: create the first user +## Creating a user β€” Keycloak In the Keycloak admin console, realm **NDP**: @@ -657,12 +657,13 @@ In the Keycloak admin console, realm **NDP**: --- -## Appendix β€” AAI API: assign groups & roles +## Assigning groups & roles β€” AAI API After the user exists in Keycloak, assign groups/roles via the **AAI API** (the caller must already be an admin): ```bash +# authenticate as an admin TOKEN=$(curl -s -X POST "$AAI/user/login" -H 'Content-Type: application/json' \ -d '{"username":"","password":""}' | jq -r .access_token) @@ -670,8 +671,15 @@ TOKEN=$(curl -s -X POST "$AAI/user/login" -H 'Content-Type: application/json' \ curl -s -X POST "$AAI/group/add-user" -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -d '{"group_name":"","username":""}' +``` + +--- -# upgrade the tier (bare name: viewer | writer | admin) +## Assigning groups & roles β€” AAI API (cont.) + +Upgrade the tier (bare name: `viewer` | `writer` | `admin`): + +```bash curl -s -X POST "$AAI/role/assign" -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -d '{"groupName":"","roleName":"writer","username":""}' From 88e293fcd70f9be9f0cc997897eec473eceabeaf Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Fri, 29 May 2026 06:51:08 -0600 Subject: [PATCH 41/67] docs(demo): split admin bootstrap by deployment (NDP infra vs full stack) Common case: the first admin is provisioned via the NDP platform onboarding (register the Endpoint). Full stack: assign ndp_admin directly in your own Keycloak. Note the historical onboarding (federation config_id + setup script, sci-ndp/NDP-EP) as a presenter note pending confirmation of the current portal. Refs #179 --- docs/demo/NDP-demo-presentation.md | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index 0bd77e1..0f1655d 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -323,23 +323,29 @@ Subsequent steps use the **web interface**, and later the Python library. ## Bootstrap the first admin The Endpoint has **no user store** β€” identity and roles come from **AAI (Keycloak)**. +How the first admin is created depends on the deployment: -The **first** admin must be set up **directly in Keycloak**, because granting roles -from the Endpoint UI or the AAI API itself requires an existing admin. +- **🟒 NDP infrastructure (common case)** β€” register your Endpoint through the NDP + platform's onboarding process. It provisions the stack and your admin access; + the platform operators manage identity. +- **πŸ§ͺ Full stack (self-hosted)** β€” you assign the admin role yourself in your own + Keycloak (next slide). -> In the common case (central NDP), the admin role is assigned by the platform -> operators in the shared AAI β€” request it from them. + --- -## Bootstrap the first admin β€” steps +## Bootstrap the first admin β€” full stack -In Keycloak (realm **NDP**): +Self-hosted only. In your Keycloak (realm **NDP**) β€” granting roles from the EP UI +or the AAI API requires an existing admin, so the first one is set here: 1. Create the user and set a password. 2. Assign the realm role **`ndp_admin`** (platform-wide), or **`group::admin`** for this Endpoint only (`EP_UUID` β†’ see appendix *Obtaining the EP_UUID*). -That user can then sign in and manage everyone else from the Endpoint. +That user can then sign in and manage everyone else via the AAI API / EP. From 550ae011cb68ba0d193d760e8494bb99a384454e Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Fri, 29 May 2026 06:56:48 -0600 Subject: [PATCH 42/67] docs(demo): clarify where users come from (NDP accounts vs self-hosted Keycloak) Common case: users are existing nationaldataplatform.com accounts (no creation needed). Full stack: create them in your own Keycloak (see appendix). Drop the duplicate create-user screenshot in favour of the appendix. Refs #179 --- docs/demo/NDP-demo-presentation.md | 10 ++++++---- docs/demo/README.md | 5 ++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index 0f1655d..87e06fe 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -351,12 +351,14 @@ That user can then sign in and manage everyone else via the AAI API / EP. --- -## Create the user (AAI) +## Where users come from (AAI) -In the Keycloak console, the administrator creates the **user** and sets a password. +Depends on the deployment: - -> The user alone **cannot publish anything yet**: they need a **role**. +- **🟒 NDP infrastructure (common case)** β€” users are existing **nationaldataplatform.com** accounts; they sign in with their NDP identity. You do not create them. +- **πŸ§ͺ Full stack (self-hosted)** β€” create them in your own **Keycloak** (Users β†’ Add user β†’ set password). β†’ see appendix *Creating a user β€” Keycloak*. + +> A user alone **cannot publish anything yet** β€” they still need a **role**. --- diff --git a/docs/demo/README.md b/docs/demo/README.md index ed02851..acddc97 100644 --- a/docs/demo/README.md +++ b/docs/demo/README.md @@ -43,9 +43,8 @@ screenshot. Checklist: - [ ] `15-docker-ps.png` β€” `docker ps` with everything "Up" **Identity and permissions** -- [ ] `19-keycloak-assign-ndp-admin.png` β€” assigning the `ndp_admin` realm role in Keycloak (first admin) -- [ ] `20-create-user.png` β€” creating a user in Keycloak -- [ ] `21-assign-role.png` β€” assigning the writer role/group in Keycloak (AAI) +- [ ] `19-keycloak-assign-ndp-admin.png` β€” assigning the `ndp_admin` realm role in Keycloak (first admin, full stack) +- [ ] `21-assign-role.png` β€” assigning the writer role/group via the AAI API **Endpoint (web)** - [ ] `30-login-and-search.png` β€” login + search From ed5376477a9ac67cd8b88ccbd57322e7b4cab181 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Fri, 29 May 2026 07:00:06 -0600 Subject: [PATCH 43/67] docs(demo): role granting via the Access Requests UI (request + approve) Replace the 'Grant the role' slide with the real UI flow: a no-role user submits a Request access form; an admin approves it on the Access Requests page with a tier (Viewer/Writer/Admin). Add UI screenshot placeholders (22-request-access, 23-access-requests-approve). Refs #179 --- docs/demo/NDP-demo-presentation.md | 21 +++++++++++++++++---- docs/demo/README.md | 3 ++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index 87e06fe..7a26a54 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -362,12 +362,25 @@ Depends on the deployment: --- -## Grant the role (AAI) +## Requesting access (user) -In **AAI** (Keycloak), the administrator gives the user a **role** β€” directly or by -adding them to a **group** that carries it. The role travels inside the token to the Endpoint. +A new user has **no role**, so the Endpoint denies access β€” but offers a +**Request access** form with an optional justification. - +![h:300](screenshots/22-request-access.png) + +> Requires `ENABLE_ACCESS_REQUESTS=True`. + +--- + +## Approving access (admin) + +On the **Access Requests** page, an admin reviews pending requests and **approves** +each with a tier β€” **Viewer**, **Writer** or **Admin** β€” or **rejects** it. + +![h:300](screenshots/23-access-requests-approve.png) + +> Approval assigns the role; the user re-logs in to pick it up. --- diff --git a/docs/demo/README.md b/docs/demo/README.md index acddc97..655a339 100644 --- a/docs/demo/README.md +++ b/docs/demo/README.md @@ -44,7 +44,8 @@ screenshot. Checklist: **Identity and permissions** - [ ] `19-keycloak-assign-ndp-admin.png` β€” assigning the `ndp_admin` realm role in Keycloak (first admin, full stack) -- [ ] `21-assign-role.png` β€” assigning the writer role/group via the AAI API +- [ ] `22-request-access.png` β€” user's "Request access" form (no role yet) +- [ ] `23-access-requests-approve.png` β€” admin Access Requests page approving with a tier **Endpoint (web)** - [ ] `30-login-and-search.png` β€” login + search From 00d5a2ef139f76c994ccd489ab3a072648a856b3 Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Fri, 29 May 2026 07:13:29 -0600 Subject: [PATCH 44/67] docs(demo): give each Access Requests screenshot its own full-size slide Split the request/approve slides so the UI screenshots sit on their own centered, larger (h:500) image slides instead of being shrunk next to text. Refs #179 --- docs/demo/NDP-demo-presentation.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/docs/demo/NDP-demo-presentation.md b/docs/demo/NDP-demo-presentation.md index 7a26a54..9ea38af 100644 --- a/docs/demo/NDP-demo-presentation.md +++ b/docs/demo/NDP-demo-presentation.md @@ -38,6 +38,8 @@ section { auto 44px, auto 44px; } +/* full-slide screenshot slides: center the image */ +section.imgslide { text-align: center; } # National Data Platform (NDP) @@ -367,23 +369,31 @@ Depends on the deployment: A new user has **no role**, so the Endpoint denies access β€” but offers a **Request access** form with an optional justification. -![h:300](screenshots/22-request-access.png) - > Requires `ENABLE_ACCESS_REQUESTS=True`. --- + + +![h:500](screenshots/22-request-access.png) + +--- + ## Approving access (admin) On the **Access Requests** page, an admin reviews pending requests and **approves** each with a tier β€” **Viewer**, **Writer** or **Admin** β€” or **rejects** it. -![h:300](screenshots/23-access-requests-approve.png) - > Approval assigns the role; the user re-logs in to pick it up. --- + + +![h:500](screenshots/23-access-requests-approve.png) + +--- + ## The three roles | Role | Can… | From 902c2b99519183622479e3f465196815ad9d295a Mon Sep 17 00:00:00 2001 From: Raul Bardaji Date: Fri, 29 May 2026 07:18:16 -0600 Subject: [PATCH 45/67] docs(demo): add screenshots (request access, approve, Affinities add endpoint) Refs #179 --- docs/demo/screenshots/22-request-access.png | Bin 0 -> 26658 bytes .../screenshots/23-access-requests-approve.png | Bin 0 -> 38009 bytes .../screenshots/A1-affinities-add-endpoint.png | Bin 0 -> 124206 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/demo/screenshots/22-request-access.png create mode 100644 docs/demo/screenshots/23-access-requests-approve.png create mode 100644 docs/demo/screenshots/A1-affinities-add-endpoint.png diff --git a/docs/demo/screenshots/22-request-access.png b/docs/demo/screenshots/22-request-access.png new file mode 100644 index 0000000000000000000000000000000000000000..05e3155cfb7d8f348db51e4c93ef5073f0d2e07b GIT binary patch literal 26658 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 QUmuX1v@)Vh(m3G10W$j@=Kufz literal 0 HcmV?d00001 diff --git a/docs/demo/screenshots/23-access-requests-approve.png b/docs/demo/screenshots/23-access-requests-approve.png new file mode 100644 index 0000000000000000000000000000000000000000..6302a9ea44e0687b2c2c86cedc6c93e123b0e92a GIT binary patch literal 38009 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
2_<4ekyLi+VJXNE_Qj`y{}cb#t7BlK#=1O)E@y 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 ZKkE0c6a1{Xe-gOY=jrO_vd$@?2>>~_&I$kk literal 0 HcmV?d00001 diff --git a/docs/demo/screenshots/A1-affinities-add-endpoint.png b/docs/demo/screenshots/A1-affinities-add-endpoint.png new file mode 100644 index 0000000000000000000000000000000000000000..2b87d282d7fbb35c1422eddcb9549ec39dbc8f4f GIT binary patch literal 124206 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