GeoVault folder-first information architecture (Phase 1)¶
Phase 1 introduces folder/workspace-first organization while keeping existing Vector/Raster pages, import routes, and ingestion handlers unchanged.
Routes added¶
| Method | Path | Purpose |
|---|---|---|
| GET | /drive |
My Drive home — folder cards |
| GET | /workspace |
Redirect → /drive (legacy) |
| GET | /drive/folders/{id} |
Folder detail — datasets in folder, Add Dataset menu |
| GET | /api/folders |
List folders (?archived=only for archived folders) |
| POST | /api/folders |
Create folder |
| GET | /api/folders/{id} |
Folder metadata |
| PUT | /api/folders/{id} |
Rename / update description |
| POST | /api/folders/{id}/archive |
Archive folder |
Routes unchanged (backward compatible)¶
All legacy paths remain registered, including:
/vectors,/rasters,/upload,/import-url,/import-s3,/esri,/discover-postgis/datasets/{name},/projects,/connections,/geoserver/*POST /projects/{id}/upload,POST /import-url,POST /import-s3,POST /api/esri/import, etc.
Vector and Raster pages now act as filtered views (GET /datasets-summary?type=vector|raster) with subtitles linking back to My Drive.
Schema changes¶
folders¶
| Column | Type | Notes |
|---|---|---|
id |
serial | Primary key |
name |
text | Unique among non-archived folders (case-insensitive index) |
description |
text | Optional |
owner_id |
int | FK dashboard_users, optional |
group_name |
text | Optional Central auth group name for visibility |
created_at |
timestamp | |
updated_at |
timestamp | |
archived_at |
timestamp | Null = active |
Spec referenced
group_id; implementation usesgroup_name(text) to align with Central group membership checks without cross-database FKs.
datasets.folder_id¶
Nullable FK to folders(id) ON DELETE SET NULL. Set on ingest when folder_id is provided.
Migration behavior¶
On metadata DB connect (db.OpenMeta):
- Schema migration creates
foldersanddatasets.folder_idif missing. EnsureDefaultFolderMigrationruns:- Creates folder "Imported Datasets" if none exists with that name.
- Sets
folder_idon all datasets wherefolder_id IS NULLand not archived.
No datasets are deleted; nothing is hidden by migration alone.
Folder-aware ingestion¶
Pass folder_id (integer) without changing ingest handlers:
| Flow | How folder_id is passed |
|---|---|
| Upload | Query: POST /projects/1/upload?folder_id={id} or form field folder_id |
| URL / S3 import | JSON body folder_id or query on POST |
| ESRI import | JSON folder_id on POST /api/esri/import (propagated through job payload) |
| PostGIS register | JSON folder_id on POST /api/datasets/register |
| GeoServer catalog import | JSON folder_id on POST /api/geoserver/catalog/import |
finalizeLocalFileIngest and UpsertVaultDataset assign folder_id on insert; existing rows keep their folder unless unset (then ingest can set via COALESCE(datasets.folder_id, EXCLUDED.folder_id)).
UI stores active folder in sessionStorage (gv_active_folder_id) and appends ?folder_id= on import navigation from a folder.
Permission inheritance¶
Folders
- No new resource type in Central.
- If
group_nameis empty: visible to any user with GeoVault service access. - If
group_nameis set: user must belong to that group (admins always allowed). - Matches existing group-based patterns (
RequireEditors,auth_group_members).
Datasets
- Unchanged:
geovault_datasetACL (view/edit/admin) still governs dataset cards and ingest authorization. - Folder listing does not bypass dataset ACL on folder detail;
datasets-summary?folder_id=only returns datasets the user may view.
Federation shell navigation¶
shared/ui/shell-config.js geovault sections:
- My Drive — workspace, archive
- Browse — Vector, Raster (legacy filters)
- Services — Connections, GeoServer, QGIS Projects
Import entries removed from the global sidebar; imports are reached via Add Dataset inside a folder.
My Drive (/drive) includes Browse (Vector, Raster) and Services (PostGIS, PostGIS Import, QGIS Projects, GeoServer) link rows matching the former workspace hub.
Known limitations (Phase 1)¶
- Flat folders only — no nesting.
- No per-user sharing / invites — group name on folder only.
- No folder-level Central resources — dataset ACLs remain per dataset.
- Archive folder does not archive datasets inside it.
- JSON catalog mode (no
DATABASE_URL): folders API and assignment require Postgres metadata. - QGIS project files are not placed in folders (still under
/projects). - Clone/rename do not move datasets between folders yet (folder_id preserved on registry row).
Related files¶
internal/db/folders.go,internal/db/migrate.gointernal/api/folders.go,internal/api/folder_context.goweb/workspace.html,web/folder.html,web/app.jsshared/ui/shell-config.js