From 26e4a1839613cc4c722155b33313899ba6ce23fe Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Tue, 3 Feb 2026 15:03:24 -0800 Subject: [PATCH] Convert wiki-links to title-based format - Add doc-card-titles mise task to enumerate cards and detect duplicates - Remove redundant aliases from zk cards (where alias matched id) - Rename reference/storage/postgresql.md title to "PostgreSQL Storage" - Convert all path-based wiki-links [[path|Title]] to title-based [[Title]] - Add pre-commit hook to check for duplicate card titles Co-Authored-By: Claude Opus 4.5 --- .pre-commit-config.yaml | 10 ++ docs/changelog.d/wiki-link-titles.doc.md | 1 + docs/index.md | 2 +- docs/reference/index.md | 62 +++---- docs/reference/infrastructure/gilbert.md | 4 +- docs/reference/infrastructure/hosts.md | 10 +- docs/reference/infrastructure/indri.md | 16 +- docs/reference/infrastructure/routing.md | 32 ++-- docs/reference/infrastructure/tailscale.md | 6 +- docs/reference/kubernetes/apps.md | 40 ++--- docs/reference/kubernetes/cluster.md | 12 +- docs/reference/kubernetes/external-secrets.md | 2 +- docs/reference/operations/backup.md | 6 +- .../reference/operations/disaster-recovery.md | 8 +- docs/reference/operations/observability.md | 8 +- docs/reference/services/1password.md | 4 +- docs/reference/services/argocd.md | 6 +- docs/reference/services/borgmatic.md | 6 +- docs/reference/services/forgejo.md | 4 +- docs/reference/services/immich.md | 10 +- docs/reference/services/jellyfin.md | 2 +- docs/reference/services/kiwix.md | 4 +- docs/reference/services/miniflux.md | 8 +- docs/reference/services/navidrome.md | 4 +- docs/reference/services/postgresql.md | 14 +- docs/reference/services/prometheus.md | 12 +- docs/reference/services/transmission.md | 4 +- docs/reference/services/zot.md | 6 +- docs/reference/storage/backups.md | 20 +-- docs/reference/storage/postgresql.md | 6 +- docs/reference/storage/sifaka.md | 24 +-- docs/zk/argocd.md | 1 - docs/zk/borgmatic.md | 1 - docs/zk/external-secrets.md | 1 - docs/zk/grafana.md | 2 - docs/zk/indri.md | 1 - docs/zk/jellyfin.md | 2 - docs/zk/kiwix.md | 2 - docs/zk/miniflux.md | 1 - docs/zk/minikube.md | 1 - docs/zk/postgresql.md | 1 - docs/zk/pulumi.md | 1 - docs/zk/teslamate.md | 1 - docs/zk/transmission.md | 2 - docs/zk/zot.md | 1 - mise-tasks/doc-card-titles | 154 ++++++++++++++++++ 46 files changed, 336 insertions(+), 189 deletions(-) create mode 100644 docs/changelog.d/wiki-link-titles.doc.md create mode 100755 mise-tasks/doc-card-titles diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d673cc3..473b2e3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -88,3 +88,13 @@ repos: - id: actionlint-system args: ['-config-file', '.github/actionlint.yaml'] files: ^\.forgejo/workflows/ + + # Documentation - check for duplicate card titles + - repo: local + hooks: + - id: doc-card-titles + name: doc-card-titles + entry: mise run doc-card-titles + language: system + files: ^docs/.*\.md$ + pass_filenames: false diff --git a/docs/changelog.d/wiki-link-titles.doc.md b/docs/changelog.d/wiki-link-titles.doc.md new file mode 100644 index 0000000..805dbcd --- /dev/null +++ b/docs/changelog.d/wiki-link-titles.doc.md @@ -0,0 +1 @@ +Convert wiki-links to title-based format and add duplicate title detection diff --git a/docs/index.md b/docs/index.md index 61f97e9..b3c9324 100644 --- a/docs/index.md +++ b/docs/index.md @@ -8,4 +8,4 @@ Welcome to the BlumeOps documentation. ## Sections -- [[reference/index|Reference]] - Technical reference cards for services, infrastructure, and operations +- [[Reference]] - Technical reference cards for services, infrastructure, and operations diff --git a/docs/reference/index.md b/docs/reference/index.md index ddcd570..cbce315 100644 --- a/docs/reference/index.md +++ b/docs/reference/index.md @@ -14,54 +14,54 @@ Individual service reference cards with URLs and configuration details. | Service | Description | Location | |---------|-------------|----------| -| [[reference/services/alloy|Alloy]] | Observability collector (metrics & logs) | indri + k8s | -| [[reference/services/argocd|ArgoCD]] | GitOps continuous delivery | k8s | -| [[reference/services/borgmatic|Borgmatic]] | Backup system | indri | -| [[reference/services/1password|1Password]] | Secrets management | cloud + k8s | -| [[reference/services/forgejo|Forgejo]] | Git forge & CI/CD | indri | -| [[reference/services/grafana|Grafana]] | Dashboards & visualization | k8s | -| [[reference/services/immich|Immich]] | Photo management | k8s | -| [[reference/services/jellyfin|Jellyfin]] | Media server | indri | -| [[reference/services/kiwix|Kiwix]] | Offline Wikipedia & ZIM archives | k8s | -| [[reference/services/loki|Loki]] | Log aggregation | k8s | -| [[reference/services/miniflux|Miniflux]] | RSS feed reader | k8s | -| [[reference/services/navidrome|Navidrome]] | Music streaming | k8s | -| [[reference/services/postgresql|PostgreSQL]] | Database cluster | k8s | -| [[reference/services/prometheus|Prometheus]] | Metrics collection | k8s | -| [[reference/services/teslamate|TeslaMate]] | Tesla data logger | k8s | -| [[reference/services/transmission|Transmission]] | BitTorrent daemon | k8s | -| [[reference/services/zot|Zot]] | Container registry | indri | +| [[Grafana Alloy|Alloy]] | Observability collector (metrics & logs) | indri + k8s | +| [[ArgoCD]] | GitOps continuous delivery | k8s | +| [[Borgmatic]] | Backup system | indri | +| [[1Password]] | Secrets management | cloud + k8s | +| [[Forgejo]] | Git forge & CI/CD | indri | +| [[Grafana]] | Dashboards & visualization | k8s | +| [[Immich]] | Photo management | k8s | +| [[Jellyfin]] | Media server | indri | +| [[Kiwix]] | Offline Wikipedia & ZIM archives | k8s | +| [[Loki]] | Log aggregation | k8s | +| [[Miniflux]] | RSS feed reader | k8s | +| [[Navidrome]] | Music streaming | k8s | +| [[PostgreSQL]] | Database cluster | k8s | +| [[Prometheus]] | Metrics collection | k8s | +| [[TeslaMate]] | Tesla data logger | k8s | +| [[Transmission]] | BitTorrent daemon | k8s | +| [[Zot]] | Container registry | indri | ## Infrastructure Host inventory and network configuration. -- [[reference/infrastructure/hosts|Hosts]] - Device inventory -- [[reference/infrastructure/indri|Indri]] - Primary server -- [[reference/infrastructure/gilbert|Gilbert]] - Development workstation -- [[reference/infrastructure/tailscale|Tailscale]] - ACLs, groups, tags -- [[reference/infrastructure/routing|Routing]] - DNS domains, port mappings +- [[Host Inventory|Hosts]] - Device inventory +- [[Indri]] - Primary server +- [[Gilbert]] - Development workstation +- [[Tailscale]] - ACLs, groups, tags +- [[Service Routing|Routing]] - DNS domains, port mappings ## Kubernetes Cluster configuration and application registry. -- [[reference/kubernetes/cluster|Cluster]] - Minikube specs, storage, networking -- [[reference/kubernetes/apps|Apps]] - ArgoCD application registry -- [[reference/kubernetes/external-secrets|External Secrets]] - Secrets management +- [[Kubernetes Cluster|Cluster]] - Minikube specs, storage, networking +- [[ArgoCD Applications|Apps]] - ArgoCD application registry +- [[External Secrets]] - Secrets management ## Storage Network storage and backup configuration. -- [[reference/storage/sifaka|Sifaka]] - Synology NAS configuration -- [[reference/storage/postgresql|PostgreSQL]] - Database cluster -- [[reference/storage/backups|Backups]] - Backup policy and schedule +- [[Sifaka NAS|Sifaka]] - Synology NAS configuration +- [[PostgreSQL Storage]] - Database cluster +- [[Backup Policy|Backups]] - Backup policy and schedule ## Operations Operational concerns and their components. -- [[reference/operations/observability|Observability]] - Metrics, logs, dashboards -- [[reference/operations/backup|Backup]] - Data protection -- [[reference/operations/disaster-recovery|Disaster Recovery]] - Recovery procedures (TBD) +- [[Observability]] - Metrics, logs, dashboards +- [[Backup]] - Data protection +- [[Disaster Recovery]] - Recovery procedures (TBD) diff --git a/docs/reference/infrastructure/gilbert.md b/docs/reference/infrastructure/gilbert.md index 4438331..7f08799 100644 --- a/docs/reference/infrastructure/gilbert.md +++ b/docs/reference/infrastructure/gilbert.md @@ -23,5 +23,5 @@ Managed via `Brewfile` and `mise.toml` in the blumeops repo. ## Related -- [[reference/infrastructure/indri|Indri]] - Server accessed from gilbert -- [[reference/kubernetes/cluster|Cluster]] - Remote k8s access +- [[Indri]] - Server accessed from gilbert +- [[Kubernetes Cluster|Cluster]] - Remote k8s access diff --git a/docs/reference/infrastructure/hosts.md b/docs/reference/infrastructure/hosts.md index 4efd9e8..bc11b36 100644 --- a/docs/reference/infrastructure/hosts.md +++ b/docs/reference/infrastructure/hosts.md @@ -12,14 +12,14 @@ All devices connected via [Tailscale](https://login.tailscale.com/) tailnet `tai | Host | Description | Card | |------|-------------|------| -| **Indri** | Mac Mini M1, 2020 - Primary server | [[reference/infrastructure/indri|Details]] | -| **Gilbert** | MacBook Air M4, 2025 - Workstation | [[reference/infrastructure/gilbert|Details]] | -| **[[reference/storage/sifaka|Sifaka]]** | Synology NAS - Storage & backups | [[reference/storage/sifaka|Details]] | +| **Indri** | Mac Mini M1, 2020 - Primary server | [[Indri|Details]] | +| **Gilbert** | MacBook Air M4, 2025 - Workstation | [[Gilbert|Details]] | +| **[[Sifaka NAS|Sifaka]]** | Synology NAS - Storage & backups | [[Sifaka NAS|Details]] | | **Mouse** | MacBook Air M2 - Allison's laptop | - | | **UniFi** | UniFi Express 7 - Home WiFi | - | | **Dwarf** | iPad Air - Employer-provided, off tailnet | - | ## Related -- [[reference/infrastructure/tailscale|Tailscale]] - Network configuration -- [[reference/infrastructure/routing|Routing]] - Service URLs +- [[Tailscale]] - Network configuration +- [[Service Routing|Routing]] - Service URLs diff --git a/docs/reference/infrastructure/indri.md b/docs/reference/infrastructure/indri.md index 6d50f3d..b93277e 100644 --- a/docs/reference/infrastructure/indri.md +++ b/docs/reference/infrastructure/indri.md @@ -22,17 +22,17 @@ Primary BlumeOps server. Mac Mini M1 (2020). ## Services Hosted **Native (via Ansible):** -- [[reference/services/forgejo|Forgejo]] - Git forge -- [[reference/services/zot|Zot]] - Container registry -- [[reference/services/jellyfin|Jellyfin]] - Media server -- [[reference/services/borgmatic|Borgmatic]] - Backup system -- [[reference/services/alloy|Alloy]] - Metrics/logs collector +- [[Forgejo]] - Git forge +- [[Zot]] - Container registry +- [[Jellyfin]] - Media server +- [[Borgmatic]] - Backup system +- [[Grafana Alloy|Alloy]] - Metrics/logs collector - Caddy - Reverse proxy for `*.ops.eblu.me` **Kubernetes (via minikube):** -- [[reference/kubernetes/apps|All k8s applications]] +- [[ArgoCD Applications|All k8s applications]] ## Related -- [[reference/infrastructure/routing|Routing]] - Port mappings -- [[reference/kubernetes/cluster|Cluster]] - Minikube details +- [[Service Routing|Routing]] - Port mappings +- [[Kubernetes Cluster|Cluster]] - Minikube details diff --git a/docs/reference/infrastructure/routing.md b/docs/reference/infrastructure/routing.md index e98d094..476b9b3 100644 --- a/docs/reference/infrastructure/routing.md +++ b/docs/reference/infrastructure/routing.md @@ -25,20 +25,20 @@ DNS points to indri's Tailscale IP (100.98.163.89). TLS via Let's Encrypt (ACME | Service | URL | Description | |---------|-----|-------------| | Homepage | https://go.ops.eblu.me | Service dashboard | -| [[reference/services/forgejo|Forgejo]] | https://forge.ops.eblu.me | Git hosting (SSH: 2222) | -| [[reference/services/zot|Zot]] | https://registry.ops.eblu.me | Container registry | -| [[reference/services/grafana|Grafana]] | https://grafana.ops.eblu.me | Dashboards | -| [[reference/services/argocd|ArgoCD]] | https://argocd.ops.eblu.me | GitOps CD | -| [[reference/services/prometheus|Prometheus]] | https://prometheus.ops.eblu.me | Metrics | -| [[reference/services/loki|Loki]] | https://loki.ops.eblu.me | Logs | -| [[reference/services/miniflux|Miniflux]] | https://feed.ops.eblu.me | RSS reader | -| [[reference/services/kiwix|Kiwix]] | https://kiwix.ops.eblu.me | Offline Wikipedia | -| [[reference/services/transmission|Transmission]] | https://torrent.ops.eblu.me | BitTorrent | -| [[reference/services/teslamate|TeslaMate]] | https://tesla.ops.eblu.me | Tesla logger | -| [[reference/services/navidrome|Navidrome]] | https://dj.ops.eblu.me | Music streaming | -| [[reference/services/jellyfin|Jellyfin]] | https://jellyfin.ops.eblu.me | Media server | -| [[reference/services/postgresql|PostgreSQL]] | pg.ops.eblu.me:5432 | Database | -| [[reference/storage/sifaka|Sifaka]] | https://nas.ops.eblu.me | NAS dashboard | +| [[Forgejo]] | https://forge.ops.eblu.me | Git hosting (SSH: 2222) | +| [[Zot]] | https://registry.ops.eblu.me | Container registry | +| [[Grafana]] | https://grafana.ops.eblu.me | Dashboards | +| [[ArgoCD]] | https://argocd.ops.eblu.me | GitOps CD | +| [[Prometheus]] | https://prometheus.ops.eblu.me | Metrics | +| [[Loki]] | https://loki.ops.eblu.me | Logs | +| [[Miniflux]] | https://feed.ops.eblu.me | RSS reader | +| [[Kiwix]] | https://kiwix.ops.eblu.me | Offline Wikipedia | +| [[Transmission]] | https://torrent.ops.eblu.me | BitTorrent | +| [[TeslaMate]] | https://tesla.ops.eblu.me | Tesla logger | +| [[Navidrome]] | https://dj.ops.eblu.me | Music streaming | +| [[Jellyfin]] | https://jellyfin.ops.eblu.me | Media server | +| [[PostgreSQL]] | pg.ops.eblu.me:5432 | Database | +| [[Sifaka NAS|Sifaka]] | https://nas.ops.eblu.me | NAS dashboard | ## Tailscale-Only Services @@ -61,5 +61,5 @@ DNS points to indri's Tailscale IP (100.98.163.89). TLS via Let's Encrypt (ACME ## Related -- [[reference/infrastructure/tailscale|Tailscale]] - ACL configuration -- [[reference/infrastructure/indri|Indri]] - Where services run +- [[Tailscale]] - ACL configuration +- [[Indri]] - Where services run diff --git a/docs/reference/infrastructure/tailscale.md b/docs/reference/infrastructure/tailscale.md index ab68246..9e89e71 100644 --- a/docs/reference/infrastructure/tailscale.md +++ b/docs/reference/infrastructure/tailscale.md @@ -17,7 +17,7 @@ ACLs managed via Pulumi in `pulumi/policy.hujson`. | Group | Members | Purpose | |-------|---------|---------| -| `group:allisonflix` | admin, member | [[reference/services/jellyfin|Jellyfin]] media access | +| `group:allisonflix` | admin, member | [[Jellyfin]] media access | ## Device Tags @@ -58,5 +58,5 @@ Pulumi uses OAuth client from 1Password (blumeops vault): ## Related -- [[reference/infrastructure/routing|Routing]] - Service URLs -- [[reference/infrastructure/hosts|Hosts]] - Device inventory +- [[Service Routing|Routing]] - Service URLs +- [[Host Inventory|Hosts]] - Device inventory diff --git a/docs/reference/kubernetes/apps.md b/docs/reference/kubernetes/apps.md index 3210634..029601f 100644 --- a/docs/reference/kubernetes/apps.md +++ b/docs/reference/kubernetes/apps.md @@ -7,33 +7,33 @@ tags: # ArgoCD Applications -Registry of all applications deployed via [[reference/services/argocd|ArgoCD]]. +Registry of all applications deployed via [[ArgoCD]]. ## Application Registry | App | Namespace | Path/Source | Service | |-----|-----------|-------------|---------| | `apps` | argocd | `argocd/apps/` | App-of-apps root | -| `argocd` | argocd | `argocd/manifests/argocd/` | [[reference/services/argocd|ArgoCD]] | +| `argocd` | argocd | `argocd/manifests/argocd/` | [[ArgoCD]] | | `tailscale-operator` | tailscale | `argocd/manifests/tailscale-operator/` | Tailscale k8s operator | -| `1password-connect` | 1password | `argocd/manifests/1password-connect/` | [[reference/services/1password|1Password]] | -| `external-secrets` | external-secrets | Helm chart | [[reference/services/1password|1Password]] | -| `external-secrets-config` | external-secrets | `argocd/manifests/external-secrets-config/` | [[reference/services/1password|1Password]] | +| `1password-connect` | 1password | `argocd/manifests/1password-connect/` | [[1Password]] | +| `external-secrets` | external-secrets | Helm chart | [[1Password]] | +| `external-secrets-config` | external-secrets | `argocd/manifests/external-secrets-config/` | [[1Password]] | | `cloudnative-pg` | cnpg-system | Helm chart (forge mirror) | PostgreSQL operator | -| `blumeops-pg` | databases | `argocd/manifests/databases/` | [[reference/services/postgresql|PostgreSQL]] | -| `prometheus` | monitoring | `argocd/manifests/prometheus/` | [[reference/services/prometheus|Prometheus]] | -| `loki` | monitoring | `argocd/manifests/loki/` | [[reference/services/loki|Loki]] | -| `grafana` | monitoring | Helm chart (forge mirror) | [[reference/services/grafana|Grafana]] | -| `grafana-config` | monitoring | `argocd/manifests/grafana-config/` | [[reference/services/grafana|Grafana]] | -| `immich` | immich | Helm chart | [[reference/services/immich|Immich]] | -| `alloy-k8s` | alloy | `argocd/manifests/alloy-k8s/` | [[reference/services/alloy|Alloy]] | +| `blumeops-pg` | databases | `argocd/manifests/databases/` | [[PostgreSQL]] | +| `prometheus` | monitoring | `argocd/manifests/prometheus/` | [[Prometheus]] | +| `loki` | monitoring | `argocd/manifests/loki/` | [[Loki]] | +| `grafana` | monitoring | Helm chart (forge mirror) | [[Grafana]] | +| `grafana-config` | monitoring | `argocd/manifests/grafana-config/` | [[Grafana]] | +| `immich` | immich | Helm chart | [[Immich]] | +| `alloy-k8s` | alloy | `argocd/manifests/alloy-k8s/` | [[Grafana Alloy|Alloy]] | | `kube-state-metrics` | monitoring | `argocd/manifests/kube-state-metrics/` | K8s metrics | -| `miniflux` | miniflux | `argocd/manifests/miniflux/` | [[reference/services/miniflux|Miniflux]] | -| `kiwix` | kiwix | `argocd/manifests/kiwix/` | [[reference/services/kiwix|Kiwix]] | -| `torrent` | torrent | `argocd/manifests/torrent/` | [[reference/services/transmission|Transmission]] | -| `navidrome` | navidrome | `argocd/manifests/navidrome/` | [[reference/services/navidrome|Navidrome]] | -| `teslamate` | teslamate | `argocd/manifests/teslamate/` | [[reference/services/teslamate|TeslaMate]] | -| `forgejo-runner` | forgejo-runner | `argocd/manifests/forgejo-runner/` | [[reference/services/forgejo|Forgejo]] CI | +| `miniflux` | miniflux | `argocd/manifests/miniflux/` | [[Miniflux]] | +| `kiwix` | kiwix | `argocd/manifests/kiwix/` | [[Kiwix]] | +| `torrent` | torrent | `argocd/manifests/torrent/` | [[Transmission]] | +| `navidrome` | navidrome | `argocd/manifests/navidrome/` | [[Navidrome]] | +| `teslamate` | teslamate | `argocd/manifests/teslamate/` | [[TeslaMate]] | +| `forgejo-runner` | forgejo-runner | `argocd/manifests/forgejo-runner/` | [[Forgejo]] CI | ## Sync Policies @@ -44,5 +44,5 @@ Registry of all applications deployed via [[reference/services/argocd|ArgoCD]]. ## Related -- [[reference/services/argocd|ArgoCD]] - GitOps platform details -- [[reference/kubernetes/cluster|Cluster]] - Kubernetes infrastructure +- [[ArgoCD]] - GitOps platform details +- [[Kubernetes Cluster|Cluster]] - Kubernetes infrastructure diff --git a/docs/reference/kubernetes/cluster.md b/docs/reference/kubernetes/cluster.md index 2b6f1d3..31fcc35 100644 --- a/docs/reference/kubernetes/cluster.md +++ b/docs/reference/kubernetes/cluster.md @@ -6,7 +6,7 @@ tags: # Kubernetes Cluster -Single-node Minikube cluster running on [[reference/infrastructure/indri|Indri]]. +Single-node Minikube cluster running on [[Indri]]. ## Cluster Specifications @@ -24,16 +24,16 @@ Single-node Minikube cluster running on [[reference/infrastructure/indri|Indri]] ## Volume Mounting -Pods mount NFS directly from [[reference/storage/sifaka|Sifaka]]. Docker NATs outbound traffic through indri's LAN IP (192.168.1.50), allowing access to Sifaka's NFS exports. +Pods mount NFS directly from [[Sifaka NAS|Sifaka]]. Docker NATs outbound traffic through indri's LAN IP (192.168.1.50), allowing access to Sifaka's NFS exports. ## Registry Mirror -Containerd uses [[reference/services/zot|Zot]] as a pull-through cache at `host.minikube.internal:5050`. +Containerd uses [[Zot]] as a pull-through cache at `host.minikube.internal:5050`. Mirrors configured: `registry.ops.eblu.me`, `docker.io`, `ghcr.io`, `quay.io` ## Related -- [[reference/kubernetes/apps|Apps]] - ArgoCD applications -- [[reference/services/argocd|ArgoCD]] - GitOps deployment -- [[reference/services/zot|Zot]] - Registry mirror +- [[ArgoCD Applications|Apps]] - ArgoCD applications +- [[ArgoCD]] - GitOps deployment +- [[Zot]] - Registry mirror diff --git a/docs/reference/kubernetes/external-secrets.md b/docs/reference/kubernetes/external-secrets.md index ac7f0ff..2b814e8 100644 --- a/docs/reference/kubernetes/external-secrets.md +++ b/docs/reference/kubernetes/external-secrets.md @@ -7,4 +7,4 @@ tags: # External Secrets -See [[reference/services/1password|1Password]] in Services. +See [[1Password]] in Services. diff --git a/docs/reference/operations/backup.md b/docs/reference/operations/backup.md index 4053b6e..fa0c627 100644 --- a/docs/reference/operations/backup.md +++ b/docs/reference/operations/backup.md @@ -10,6 +10,6 @@ Daily automated backups of BlumeOps data. ## Components -- [[reference/services/borgmatic|Borgmatic]] - Backup orchestration -- [[reference/storage/sifaka|Sifaka]] - Backup target (NAS) -- [[reference/storage/backups|Backup Policy]] - What gets backed up and retention +- [[Borgmatic]] - Backup orchestration +- [[Sifaka NAS|Sifaka]] - Backup target (NAS) +- [[Backup Policy]] - What gets backed up and retention diff --git a/docs/reference/operations/disaster-recovery.md b/docs/reference/operations/disaster-recovery.md index 406ac67..e32be67 100644 --- a/docs/reference/operations/disaster-recovery.md +++ b/docs/reference/operations/disaster-recovery.md @@ -8,12 +8,12 @@ tags: TBD. Current state: -- [[reference/services/borgmatic|Borgmatic]] provides daily backups to [[reference/storage/sifaka|Sifaka]] +- [[Borgmatic]] provides daily backups to [[Sifaka NAS|Sifaka]] - Infrastructure can be rebootstrapped using the blumeops repo - Detailed DR procedures not yet documented ## Components -- [[reference/services/borgmatic|Borgmatic]] - Backup restoration -- [[reference/services/1password|1Password]] - Credential recovery -- [[reference/services/forgejo|Forgejo]] - Source of truth for infrastructure code +- [[Borgmatic]] - Backup restoration +- [[1Password]] - Credential recovery +- [[Forgejo]] - Source of truth for infrastructure code diff --git a/docs/reference/operations/observability.md b/docs/reference/operations/observability.md index 613b071..1e79c07 100644 --- a/docs/reference/operations/observability.md +++ b/docs/reference/operations/observability.md @@ -10,7 +10,7 @@ Metrics, logs, and dashboards for BlumeOps infrastructure. ## Components -- [[reference/services/prometheus|Prometheus]] - Metrics storage and querying -- [[reference/services/loki|Loki]] - Log aggregation -- [[reference/services/alloy|Alloy]] - Metrics and log collection -- [[reference/services/grafana|Grafana]] - Dashboards and visualization +- [[Prometheus]] - Metrics storage and querying +- [[Loki]] - Log aggregation +- [[Grafana Alloy|Alloy]] - Metrics and log collection +- [[Grafana]] - Dashboards and visualization diff --git a/docs/reference/services/1password.md b/docs/reference/services/1password.md index b97681a..2db7f59 100644 --- a/docs/reference/services/1password.md +++ b/docs/reference/services/1password.md @@ -36,5 +36,5 @@ Services reference 1Password items via `ExternalSecret` manifests. ## Related -- [[reference/services/argocd|ArgoCD]] - Uses secrets for git access -- [[reference/services/postgresql|PostgreSQL]] - Database credentials +- [[ArgoCD]] - Uses secrets for git access +- [[PostgreSQL]] - Database credentials diff --git a/docs/reference/services/argocd.md b/docs/reference/services/argocd.md index ceea331..b944d7f 100644 --- a/docs/reference/services/argocd.md +++ b/docs/reference/services/argocd.md @@ -7,7 +7,7 @@ tags: # ArgoCD -GitOps continuous delivery platform for the [[reference/kubernetes/cluster|Kubernetes cluster]]. +GitOps continuous delivery platform for the [[Kubernetes Cluster|Kubernetes cluster]]. ## Quick Reference @@ -33,5 +33,5 @@ GitOps continuous delivery platform for the [[reference/kubernetes/cluster|Kuber ## Related -- [[reference/kubernetes/apps|Apps]] - Full application registry -- [[reference/services/forgejo|Forgejo]] - Git source +- [[ArgoCD Applications|Apps]] - Full application registry +- [[Forgejo]] - Git source diff --git a/docs/reference/services/borgmatic.md b/docs/reference/services/borgmatic.md index 8895538..2c26647 100644 --- a/docs/reference/services/borgmatic.md +++ b/docs/reference/services/borgmatic.md @@ -16,7 +16,7 @@ Daily backup system using Borg backup, running on indri. | **Install** | mise (pipx) | | **Config** | `~/.config/borgmatic/config.yaml` | | **Schedule** | Daily at 2:00 AM | -| **Repository** | `/Volumes/backups/borg/` on [[reference/storage/sifaka|Sifaka]] | +| **Repository** | `/Volumes/backups/borg/` on [[Sifaka NAS|Sifaka]] | ## What Gets Backed Up @@ -55,6 +55,6 @@ Dashboard: "Borgmatic Backups" in [[grafana|Grafana]] ## Related -- [[reference/storage/backups|Backups]] - Full backup policy -- [[reference/storage/sifaka|Sifaka]] - Backup target +- [[Backup Policy|Backups]] - Full backup policy +- [[Sifaka NAS|Sifaka]] - Backup target - [[postgresql|PostgreSQL]] - Database backups diff --git a/docs/reference/services/forgejo.md b/docs/reference/services/forgejo.md index 0889efa..ff5a0d0 100644 --- a/docs/reference/services/forgejo.md +++ b/docs/reference/services/forgejo.md @@ -44,5 +44,5 @@ Managed via 1Password: `lfs-jwt-secret`, `internal-token`, `oauth2-jwt-secret`, ## Related -- [[reference/services/argocd|ArgoCD]] - Uses Forgejo as git source -- [[reference/services/zot|Zot]] - Container registry for built images +- [[ArgoCD]] - Uses Forgejo as git source +- [[Zot]] - Container registry for built images diff --git a/docs/reference/services/immich.md b/docs/reference/services/immich.md index 6d53894..df76d37 100644 --- a/docs/reference/services/immich.md +++ b/docs/reference/services/immich.md @@ -16,11 +16,11 @@ Self-hosted photo and video management. | **URL** | https://photos.ops.eblu.me | | **Namespace** | `immich` | | **Deployment** | Helm chart (k8s) | -| **Database** | [[reference/services/postgresql|PostgreSQL]] (CNPG) | -| **Storage** | [[reference/storage/sifaka|Sifaka]] photos volume | +| **Database** | [[PostgreSQL]] (CNPG) | +| **Storage** | [[Sifaka NAS|Sifaka]] photos volume | ## Related -- [[reference/services/postgresql|PostgreSQL]] - Database backend -- [[reference/storage/sifaka|Sifaka]] - Photo storage -- [[reference/services/jellyfin|Jellyfin]] - Video streaming (separate service) +- [[PostgreSQL]] - Database backend +- [[Sifaka NAS|Sifaka]] - Photo storage +- [[Jellyfin]] - Video streaming (separate service) diff --git a/docs/reference/services/jellyfin.md b/docs/reference/services/jellyfin.md index eea7c21..0eb13ce 100644 --- a/docs/reference/services/jellyfin.md +++ b/docs/reference/services/jellyfin.md @@ -48,4 +48,4 @@ Dashboard > Playback: ## Related - [[navidrome|Navidrome]] - Music streaming -- [[reference/storage/sifaka|Sifaka]] - Media storage +- [[Sifaka NAS|Sifaka]] - Media storage diff --git a/docs/reference/services/kiwix.md b/docs/reference/services/kiwix.md index 89b2a3a..5e2bb7a 100644 --- a/docs/reference/services/kiwix.md +++ b/docs/reference/services/kiwix.md @@ -17,7 +17,7 @@ Offline Wikipedia and ZIM archive server. | **Tailscale URL** | https://kiwix.tail8d86e.ts.net | | **Namespace** | `kiwix` | | **Image** | `ghcr.io/kiwix/kiwix-serve:3.8.1` | -| **Storage** | NFS from [[reference/storage/sifaka|Sifaka]] (`/volume1/torrents`) | +| **Storage** | NFS from [[Sifaka NAS|Sifaka]] (`/volume1/torrents`) | ## Architecture @@ -49,4 +49,4 @@ Full list: `argocd/manifests/kiwix/configmap-zim-torrents.yaml` ## Related - [[transmission|Transmission]] - Downloads ZIM files -- [[reference/storage/sifaka|Sifaka]] - ZIM storage +- [[Sifaka NAS|Sifaka]] - ZIM storage diff --git a/docs/reference/services/miniflux.md b/docs/reference/services/miniflux.md index f68bf37..b99a8b0 100644 --- a/docs/reference/services/miniflux.md +++ b/docs/reference/services/miniflux.md @@ -17,7 +17,7 @@ Minimalist RSS/Atom feed reader. | **Tailscale URL** | https://feed.tail8d86e.ts.net | | **Namespace** | `miniflux` | | **Image** | `ghcr.io/miniflux/miniflux:latest` | -| **Database** | [[reference/services/postgresql|PostgreSQL]] | +| **Database** | [[PostgreSQL]] | ## Features @@ -33,9 +33,9 @@ Uses CloudNativePG cluster at `pg.ops.eblu.me`. Database user password stored in ## Backup -Feed subscriptions and read state backed up via [[reference/services/borgmatic|Borgmatic]] PostgreSQL hook. +Feed subscriptions and read state backed up via [[Borgmatic]] PostgreSQL hook. ## Related -- [[reference/services/postgresql|PostgreSQL]] - Database backend -- [[reference/services/borgmatic|Borgmatic]] - Data backup +- [[PostgreSQL]] - Database backend +- [[Borgmatic]] - Data backup diff --git a/docs/reference/services/navidrome.md b/docs/reference/services/navidrome.md index 3144403..e6c08db 100644 --- a/docs/reference/services/navidrome.md +++ b/docs/reference/services/navidrome.md @@ -38,5 +38,5 @@ The `/data` directory contains SQLite database, configuration, and cache. ## Related -- [[reference/services/jellyfin|Jellyfin]] - Video streaming -- [[reference/storage/sifaka|Sifaka]] - Music storage +- [[Jellyfin]] - Video streaming +- [[Sifaka NAS|Sifaka]] - Music storage diff --git a/docs/reference/services/postgresql.md b/docs/reference/services/postgresql.md index c254249..e71bf3e 100644 --- a/docs/reference/services/postgresql.md +++ b/docs/reference/services/postgresql.md @@ -23,8 +23,8 @@ Database cluster via CloudNativePG operator. | Database | Owner | Purpose | |----------|-------|---------| -| miniflux | miniflux | [[reference/services/miniflux|Miniflux]] feed data | -| teslamate | teslamate | [[reference/services/teslamate|TeslaMate]] vehicle data | +| miniflux | miniflux | [[Miniflux]] feed data | +| teslamate | teslamate | [[TeslaMate]] vehicle data | ## Users @@ -34,11 +34,11 @@ Database cluster via CloudNativePG operator. | miniflux | app owner | Owns miniflux database | | teslamate | superuser | TeslaMate (needs extensions) | | eblume | superuser | Admin access | -| borgmatic | pg_read_all_data | [[reference/services/borgmatic|Backup]] access | +| borgmatic | pg_read_all_data | [[Borgmatic|Backup]] access | ## Backup -Backed up via [[reference/services/borgmatic|Borgmatic]] `postgresql_databases` hook. Streams `pg_dump` directly to Borg (no intermediate files, no downtime). See [[reference/operations/backup|Backup]] for overall backup policy. +Backed up via [[Borgmatic]] `postgresql_databases` hook. Streams `pg_dump` directly to Borg (no intermediate files, no downtime). See [[Backup]] for overall backup policy. ## Credentials @@ -54,6 +54,6 @@ Backed up via [[reference/services/borgmatic|Borgmatic]] `postgresql_databases` ## Related -- [[reference/services/miniflux|Miniflux]] - Feed reader database -- [[reference/services/teslamate|TeslaMate]] - Vehicle data database -- [[reference/services/borgmatic|Borgmatic]] - Database backup +- [[Miniflux]] - Feed reader database +- [[TeslaMate]] - Vehicle data database +- [[Borgmatic]] - Database backup diff --git a/docs/reference/services/prometheus.md b/docs/reference/services/prometheus.md index 3b6b32f..0966c2c 100644 --- a/docs/reference/services/prometheus.md +++ b/docs/reference/services/prometheus.md @@ -23,19 +23,19 @@ Metrics storage and querying for BlumeOps infrastructure. ## Data Sources ### Remote Write (from Alloy) -- Indri system metrics via [[reference/services/alloy|Alloy]] remote_write +- Indri system metrics via [[Grafana Alloy|Alloy]] remote_write - Textfile metrics: minikube, borgmatic, zot, jellyfin ### Scrape Targets | Target | Metrics | |--------|---------| -| `sifaka:9100` | [[reference/storage/sifaka|Sifaka]] NAS (node_exporter) | -| `cnpg-metrics.tail8d86e.ts.net:9187` | [[reference/services/postgresql|CloudNativePG]] metrics | +| `sifaka:9100` | [[Sifaka NAS|Sifaka]] NAS (node_exporter) | +| `cnpg-metrics.tail8d86e.ts.net:9187` | [[PostgreSQL|CloudNativePG]] metrics | | `kube-state-metrics.monitoring.svc:8080` | Kubernetes resource metrics | ## Related -- [[reference/services/alloy|Alloy]] - Metrics collector -- [[reference/services/grafana|Grafana]] - Visualization -- [[reference/services/loki|Loki]] - Logs counterpart +- [[Grafana Alloy|Alloy]] - Metrics collector +- [[Grafana]] - Visualization +- [[Loki]] - Logs counterpart diff --git a/docs/reference/services/transmission.md b/docs/reference/services/transmission.md index 0676431..80fd138 100644 --- a/docs/reference/services/transmission.md +++ b/docs/reference/services/transmission.md @@ -17,7 +17,7 @@ BitTorrent daemon, primarily for downloading ZIM archives for [[kiwix|Kiwix]]. | **Tailscale URL** | https://torrent.tail8d86e.ts.net | | **Namespace** | `torrent` | | **Image** | `lscr.io/linuxserver/transmission:latest` | -| **Storage** | NFS PVC from [[reference/storage/sifaka|Sifaka]] | +| **Storage** | NFS PVC from [[Sifaka NAS|Sifaka]] | ## Storage Layout @@ -50,4 +50,4 @@ Web UI shows: active/seeding/paused counts, speeds, disk usage. ## Related - [[kiwix|Kiwix]] - ZIM archive consumer -- [[reference/storage/sifaka|Sifaka]] - Download storage +- [[Sifaka NAS|Sifaka]] - Download storage diff --git a/docs/reference/services/zot.md b/docs/reference/services/zot.md index d40b452..ecab117 100644 --- a/docs/reference/services/zot.md +++ b/docs/reference/services/zot.md @@ -30,7 +30,7 @@ OCI-native container registry providing pull-through cache and private image sto ## Pull-Through Cache -When [[reference/kubernetes/cluster|minikube]] pulls an image, containerd checks zot first. If cached, returns immediately. If not, zot fetches from upstream, caches it, then returns. +When [[Kubernetes Cluster|minikube]] pulls an image, containerd checks zot first. If cached, returns immediately. If not, zot fetches from upstream, caches it, then returns. ## Security Model @@ -38,5 +38,5 @@ Network access only (no authentication). Defense is the Tailscale ACL boundary. ## Related -- [[reference/services/forgejo|Forgejo]] - Container build CI -- [[reference/kubernetes/cluster|Cluster]] - Registry consumer +- [[Forgejo]] - Container build CI +- [[Kubernetes Cluster|Cluster]] - Registry consumer diff --git a/docs/reference/storage/backups.md b/docs/reference/storage/backups.md index 880c056..ded19c8 100644 --- a/docs/reference/storage/backups.md +++ b/docs/reference/storage/backups.md @@ -7,13 +7,13 @@ tags: # Backup Policy -Daily automated backups from [[reference/infrastructure/indri|Indri]] to [[reference/storage/sifaka|Sifaka]] NAS. +Daily automated backups from [[Indri]] to [[Sifaka NAS|Sifaka]] NAS. ## Schedule | Time | Frequency | System | |------|-----------|--------| -| 2:00 AM | Daily | [[reference/services/borgmatic|Borgmatic]] | +| 2:00 AM | Daily | [[Borgmatic]] | ## What Gets Backed Up @@ -31,8 +31,8 @@ Daily automated backups from [[reference/infrastructure/indri|Indri]] to [[refer | Database | Host | Method | |----------|------|--------| -| miniflux | [[reference/services/postgresql|pg.ops.eblu.me]] | pg_dump stream | -| teslamate | [[reference/services/postgresql|pg.ops.eblu.me]] | pg_dump stream | +| miniflux | [[PostgreSQL|pg.ops.eblu.me]] | pg_dump stream | +| teslamate | [[PostgreSQL|pg.ops.eblu.me]] | pg_dump stream | ## What Is NOT Backed Up @@ -53,19 +53,19 @@ Daily automated backups from [[reference/infrastructure/indri|Indri]] to [[refer ## Backup Target -Repository: `/Volumes/backups/borg/` on [[reference/storage/sifaka|Sifaka]] +Repository: `/Volumes/backups/borg/` on [[Sifaka NAS|Sifaka]] ## Monitoring -Metrics exposed to [[reference/services/prometheus|Prometheus]]: +Metrics exposed to [[Prometheus]]: - `borgmatic_up` - Repository accessible - `borgmatic_last_archive_timestamp` - Last backup time - `borgmatic_repo_deduplicated_size_bytes` - Disk usage -Dashboard: "Borgmatic Backups" in [[reference/services/grafana|Grafana]] +Dashboard: "Borgmatic Backups" in [[Grafana]] ## Related -- [[reference/services/borgmatic|Borgmatic]] - Backup system details -- [[reference/storage/sifaka|Sifaka]] - Backup storage -- [[reference/services/postgresql|PostgreSQL]] - Database backups +- [[Borgmatic]] - Backup system details +- [[Sifaka NAS|Sifaka]] - Backup storage +- [[PostgreSQL]] - Database backups diff --git a/docs/reference/storage/postgresql.md b/docs/reference/storage/postgresql.md index f6e3695..8742569 100644 --- a/docs/reference/storage/postgresql.md +++ b/docs/reference/storage/postgresql.md @@ -1,10 +1,10 @@ --- -title: PostgreSQL +title: PostgreSQL Storage tags: - storage - database --- -# PostgreSQL +# PostgreSQL Storage -See [[reference/services/postgresql|PostgreSQL]] in Services. +See [[PostgreSQL]] in Services. diff --git a/docs/reference/storage/sifaka.md b/docs/reference/storage/sifaka.md index b4d2235..38249cb 100644 --- a/docs/reference/storage/sifaka.md +++ b/docs/reference/storage/sifaka.md @@ -21,11 +21,11 @@ Synology NAS providing network storage and backup target. | Share | Path | Purpose | Consumers | |-------|------|---------|-----------| -| backups | `/volume1/backups` | Borg backup repository | [[reference/services/borgmatic|Borgmatic]] | -| torrents | `/volume1/torrents` | ZIM downloads | [[reference/services/kiwix|Kiwix]], [[reference/services/transmission|Transmission]] | -| music | `/volume1/music` | Music library | [[reference/services/navidrome|Navidrome]] | -| allisonflix | `/volume1/allisonflix` | Video library | [[reference/services/jellyfin|Jellyfin]] | -| photos | `/volume1/photos` | Photo library | [[reference/services/immich|Immich]] | +| backups | `/volume1/backups` | Borg backup repository | [[Borgmatic]] | +| torrents | `/volume1/torrents` | ZIM downloads | [[Kiwix]], [[Transmission]] | +| music | `/volume1/music` | Music library | [[Navidrome]] | +| allisonflix | `/volume1/allisonflix` | Video library | [[Jellyfin]] | +| photos | `/volume1/photos` | Photo library | [[Immich]] | ## NFS Exports @@ -37,7 +37,7 @@ Synology NAS providing network storage and backup target. ## Monitoring -Node exporter running in Docker container, scraped by [[reference/services/prometheus|Prometheus]] at `sifaka:9100`. +Node exporter running in Docker container, scraped by [[Prometheus]] at `sifaka:9100`. ## Tailscale @@ -46,14 +46,14 @@ Node exporter running in Docker container, scraped by [[reference/services/prome ## Backup -Sifaka is the **target** for [[reference/operations/backup|backups]], not a backup source. [[reference/services/borgmatic|Borgmatic]] sends backups TO sifaka, not OF sifaka. +Sifaka is the **target** for [[Backup|backups]], not a backup source. [[Borgmatic]] sends backups TO sifaka, not OF sifaka. Data protection for sifaka itself currently relies on the Synology RAID 5 configuration, which provides single-disk fault tolerance. Future plans include offsite duplication for additional resiliency. ## Related -- [[reference/storage/backups|Backups]] - Backup policy -- [[reference/services/borgmatic|Borgmatic]] - Backup system -- [[reference/services/immich|Immich]] - Photo consumer -- [[reference/services/jellyfin|Jellyfin]] - Media consumer -- [[reference/services/navidrome|Navidrome]] - Music consumer +- [[Backup Policy|Backups]] - Backup policy +- [[Borgmatic]] - Backup system +- [[Immich]] - Photo consumer +- [[Jellyfin]] - Media consumer +- [[Navidrome]] - Music consumer diff --git a/docs/zk/argocd.md b/docs/zk/argocd.md index d22c2fb..7a1f325 100644 --- a/docs/zk/argocd.md +++ b/docs/zk/argocd.md @@ -1,7 +1,6 @@ --- id: argocd aliases: - - argocd - argo-cd tags: - blumeops diff --git a/docs/zk/borgmatic.md b/docs/zk/borgmatic.md index bfe54bc..87ccf05 100644 --- a/docs/zk/borgmatic.md +++ b/docs/zk/borgmatic.md @@ -1,7 +1,6 @@ --- id: borgmatic aliases: - - borgmatic - borg-backup tags: - blumeops diff --git a/docs/zk/external-secrets.md b/docs/zk/external-secrets.md index 64c6a60..3eccda4 100644 --- a/docs/zk/external-secrets.md +++ b/docs/zk/external-secrets.md @@ -1,7 +1,6 @@ --- id: external-secrets aliases: - - external-secrets - eso - external-secrets-operator tags: diff --git a/docs/zk/grafana.md b/docs/zk/grafana.md index a086b2b..1d9ff9c 100644 --- a/docs/zk/grafana.md +++ b/docs/zk/grafana.md @@ -1,7 +1,5 @@ --- id: grafana -aliases: - - grafana tags: - blumeops --- diff --git a/docs/zk/indri.md b/docs/zk/indri.md index 206f8aa..6f4047d 100644 --- a/docs/zk/indri.md +++ b/docs/zk/indri.md @@ -1,7 +1,6 @@ --- id: indri aliases: - - indri - mac-mini tags: - blumeops diff --git a/docs/zk/jellyfin.md b/docs/zk/jellyfin.md index a0e6129..132b55b 100644 --- a/docs/zk/jellyfin.md +++ b/docs/zk/jellyfin.md @@ -1,7 +1,5 @@ --- id: jellyfin -aliases: - - jellyfin tags: - blumeops --- diff --git a/docs/zk/kiwix.md b/docs/zk/kiwix.md index 20021c0..5e19bb5 100644 --- a/docs/zk/kiwix.md +++ b/docs/zk/kiwix.md @@ -1,7 +1,5 @@ --- id: kiwix -aliases: - - kiwix tags: - blumeops --- diff --git a/docs/zk/miniflux.md b/docs/zk/miniflux.md index d0969cf..a516d6a 100644 --- a/docs/zk/miniflux.md +++ b/docs/zk/miniflux.md @@ -1,7 +1,6 @@ --- id: miniflux aliases: - - miniflux - feed - rss tags: diff --git a/docs/zk/minikube.md b/docs/zk/minikube.md index dbf6aa3..ac47025 100644 --- a/docs/zk/minikube.md +++ b/docs/zk/minikube.md @@ -1,7 +1,6 @@ --- id: minikube aliases: - - minikube - kubernetes - k8s tags: diff --git a/docs/zk/postgresql.md b/docs/zk/postgresql.md index fd2014c..f8d35d1 100644 --- a/docs/zk/postgresql.md +++ b/docs/zk/postgresql.md @@ -1,7 +1,6 @@ --- id: postgresql aliases: - - postgresql - postgres - pg tags: diff --git a/docs/zk/pulumi.md b/docs/zk/pulumi.md index dbe071c..f9e0189 100644 --- a/docs/zk/pulumi.md +++ b/docs/zk/pulumi.md @@ -1,7 +1,6 @@ --- id: pulumi aliases: - - pulumi - tailnet-iac tags: - blumeops diff --git a/docs/zk/teslamate.md b/docs/zk/teslamate.md index 195cb2b..8684a36 100644 --- a/docs/zk/teslamate.md +++ b/docs/zk/teslamate.md @@ -1,7 +1,6 @@ --- id: teslamate aliases: - - teslamate - tesla tags: - blumeops diff --git a/docs/zk/transmission.md b/docs/zk/transmission.md index 5d8e6fd..9a46834 100644 --- a/docs/zk/transmission.md +++ b/docs/zk/transmission.md @@ -1,7 +1,5 @@ --- id: transmission -aliases: - - transmission tags: - blumeops --- diff --git a/docs/zk/zot.md b/docs/zk/zot.md index 578ec48..113d2fe 100644 --- a/docs/zk/zot.md +++ b/docs/zk/zot.md @@ -1,7 +1,6 @@ --- id: zot aliases: - - zot - container-registry tags: - blumeops diff --git a/mise-tasks/doc-card-titles b/mise-tasks/doc-card-titles new file mode 100755 index 0000000..c791f1b --- /dev/null +++ b/mise-tasks/doc-card-titles @@ -0,0 +1,154 @@ +#!/usr/bin/env -S uv run --script +# /// script +# requires-python = ">=3.12" +# dependencies = ["pyyaml>=6.0", "rich>=13.0.0"] +# /// +#MISE description="List all doc card titles and detect duplicates" +"""List all documentation card titles/IDs and detect duplicates. + +This script scans all markdown files in the docs/ directory (excluding +changelog.d/), extracts frontmatter titles, IDs, and aliases, and reports +any duplicates or conflicts that could cause wiki-link resolution issues. + +Usage: mise run doc-card-titles +""" + +import sys +from collections import defaultdict +from pathlib import Path + +import yaml +from rich.console import Console +from rich.table import Table + +DOCS_DIR = Path(__file__).parent.parent / "docs" + + +def extract_frontmatter(file_path: Path) -> dict | None: + """Extract YAML frontmatter from a markdown file.""" + content = file_path.read_text() + if not content.startswith("---"): + return None + + # Find the closing --- + end_idx = content.find("---", 3) + if end_idx == -1: + return None + + frontmatter_text = content[3:end_idx].strip() + try: + return yaml.safe_load(frontmatter_text) or {} + except yaml.YAMLError: + return None + + +def main() -> int: + console = Console() + + # Collect all titles/IDs and their source files + # Key: identifier (title, id, or alias), Value: list of (file_path, identifier_type) + identifiers: dict[str, list[tuple[str, str]]] = defaultdict(list) + + # Scan all markdown files + for md_file in sorted(DOCS_DIR.rglob("*.md")): + # Skip changelog fragments + if "changelog.d" in md_file.parts: + continue + + rel_path = md_file.relative_to(DOCS_DIR) + frontmatter = extract_frontmatter(md_file) + + if not frontmatter: + continue + + # Extract title (used by reference docs) + title = frontmatter.get("title") + if title: + identifiers[title].append((str(rel_path), "title")) + + # Extract id (used by zk cards) + card_id = frontmatter.get("id") + if card_id: + identifiers[card_id].append((str(rel_path), "id")) + + # Extract aliases + aliases = frontmatter.get("aliases", []) + if aliases: + for alias in aliases: + identifiers[alias].append((str(rel_path), "alias")) + + # Separate into duplicates and unique + duplicates: dict[str, list[tuple[str, str]]] = {} + unique: dict[str, tuple[str, str]] = {} + + for identifier, sources in identifiers.items(): + if len(sources) > 1: + duplicates[identifier] = sources + else: + unique[identifier] = sources[0] + + # Print results + console.print("[bold]Doc Card Title Inventory[/bold]") + console.print() + + # Duplicates table (if any) + if duplicates: + console.print("[bold red]Duplicates Found[/bold red]") + dup_table = Table(show_header=True, header_style="bold") + dup_table.add_column("Identifier") + dup_table.add_column("Type") + dup_table.add_column("File") + + for identifier in sorted(duplicates.keys()): + sources = duplicates[identifier] + first = True + for file_path, id_type in sources: + dup_table.add_row( + identifier if first else "", + id_type, + file_path, + ) + first = False + + console.print(dup_table) + console.print() + + # All identifiers table + console.print("[bold]All Identifiers[/bold]") + all_table = Table(show_header=True, header_style="bold") + all_table.add_column("Identifier") + all_table.add_column("Type") + all_table.add_column("File") + all_table.add_column("Status") + + for identifier in sorted(identifiers.keys()): + sources = identifiers[identifier] + is_dup = identifier in duplicates + first = True + for file_path, id_type in sources: + status = "[red]DUPLICATE[/red]" if is_dup else "[green]OK[/green]" + all_table.add_row( + identifier if first else "", + id_type, + file_path, + status if first else "", + ) + first = False + + console.print(all_table) + + # Summary + console.print() + console.print(f"Total identifiers: {len(identifiers)}") + console.print(f"Duplicates: {len(duplicates)}") + + if duplicates: + console.print() + console.print("[bold red]Action required:[/bold red] Resolve duplicates to ensure wiki-links work correctly.") + return 1 + + return 0 + + +if __name__ == "__main__": + sys.exit(main())