Handoff — docs-angular, cloud docs config, landing integration
Comprehensive documentation system guides
Handoff: docs-angular context, landing links, and moving private-project auth to cloud/MongoDB
This document captures what was verified in the codebase (March 2026) and recommended next steps. Product focus stays on the landing site (deploy/gograb-landing/); docs work is a separate track unless explicitly scoped.
1. What docs-angular is
- App path:
apps/docs-angular/(Nx app). - Production routing: Hash-based URL strategy when
environment.productionis true — seeprovideRouter(..., withHashLocation())insrc/app/app.config.ts. Paths look likehttps://docs.gograb.space/#/select-project, not/docson arbitrary hosts. - Bootstrap:
APP_INITIALIZERloads dynamic routes viaDynamicRoutesService.generateDynamicRoutes(), thenDocsAppModeService, then NGXSLoadPersistedProject. Routes are reset after generation (router.resetConfig).
Canonical public entry for marketing links
- Use:
https://docs.gograb.space/#/select-project - Avoid: relative
/docson the landing host (breaks on Cloudflare Pages previews and onfile://opens — resolves tofile:///docs).
Landing repo alignment
deploy/gograb-landing/index.htmlandtest-versions/index-v8.htmlshould use the absolute docs URL above for “Docs” CTAs.deploy/gograb-landing/DEPLOY.mddocuments this and optional View Session links.
2. Project list and selection (NGXS)
- State:
src/app/state/project-selection.state.ts—ProjectSelectionState. - Sources:
- Local / dev:
GET assets/docs-folders-config.json(with cache-busting). - Cloud mode: folders config via
DocsApiService/ cloud (LoadAvailableProjectsbranches ondocsAppMode.docsAppMode() === 'cloud').
- Local / dev:
- Persistence: Selected project in
localStorageunderdocs-selected-project(JSON). NGXS storage plugin also persistsprojectSelection/projectDocs. - Root projects: Only folder nodes with
isRoot: trueunder each language (english/spanish) become selectable “projects.” Nodes withpasswordbut withoutisRootare containers, not projects (skipped inProjectSelectionStateandAccessService.deriveProjectsFromFoldersConfig).
3. View sessions (subset of projects via share link)
Purpose: Restrict which projects appear for a given link (e.g. partner or public subset) without exposing the full catalog.
Frontend
- URL patterns parsed in
ProjectSelectionState.getViewSessionContextFromUrl():- Query:
?v=,?session=,?vs=,?go= - Hash:
#/v/:token,#/share/:token,#/go/:slug
- Query:
- Routes in
DynamicRoutesService.getBaseRoutes():v/:token,share/:token,go/:slug→ViewSessionEntryComponent, which redirects toselect-projectwith the right query params. - Admin-generated links (
src/app/admin/view-sessions/view-sessions.component.ts):buildShareableLink()→origin/#/v/{token}ororigin/#/go/{slug}.
Backend
APIs/backend-docs-api/src/app/view-sessions/view-sessions.controller.ts- Public:
GET /sessions/:token,GET /sessions/by-slug/:slug→{ allowedProjectIds } - Admin: list/create/deactivate (roles: exec/dev/admin/system).
- Public:
Client API base
ProjectSelectionStateresolves view sessions againstDOCS_API_URL(must be backend-docs-api, e.g./docs-apiorhttps://docs-api.gograb.space/...depending on deploy). Wrong base = silent filter failure.
4. Private projects and passwords (current design — to improve)
Where passwords live today
- File:
apps/docs-angular/src/assets/docs-folders-config.json - Shape: Under
folders[]→ language folder →children[]: each root project may include"password": "<plaintext>". Presence ofpasswordimplies private visibility in derived metadata. - Cloud: Same JSON may be served from the docs API in cloud mode — deployed config can differ from git.
Runtime behavior
AccessService(src/app/services/access.service.ts):deriveProjectsFromFoldersConfig()buildsDocsProject[]withvisibility: 'private'whenpasswordis set.unlockProject(projectId, inputPassword)compares trimmed plaintext equality:expected === inputPassword.- Unlock flags:
localStoragekeysdocs-project-unlocked:{projectId}and cross-languagedocs-project-unlocked:{projectName}. matchPrivateProjectsByPassword()powers “View Private Projects” modal (private-project-modal) — finds all private root projects whose password exactly matches.
- Security posture: Passwords are effectively public in the client bundle/config for anyone who can read
docs-folders-config.jsonor the cloud payload. This is acceptable only for low-friction gating, not real secrecy.
UI touchpoints
src/app/shared/private-project-modal/— bulk password search.project-switcher,docs-page,project-selection— per-project unlock flows.
5. Recommendations: move private access to cloud/MongoDB (next agent)
Goals
- No plaintext passwords in browser-loaded JSON; optionally no password field in folders config at all.
- Server-side verification (e.g.
POST /docs-api/projects/:id/unlockwith password body, or session cookie/JWT after success). - MongoDB (or existing docs DB) stores hashed credentials per project or per “doc space,” with audit fields (createdBy, rotatedAt).
Suggested phases
| Phase | Action |
|---|---|
| A | Schema: DocProjectAccess or extend existing docs collections with projectId, passwordHash, salt/argon2id params, active. |
| B | API: challenge/response or single POST verify; rate-limit; return short-lived session token or httpOnly cookie scoped to docs domain. |
| C | docs-angular: Replace unlockProject plaintext compare with API call; store token in memory/sessionStorage (not long-lived secrets); keep NGXS “unlocked” derived from validated session. |
| D | Migration: one-time script to import from current docs-folders-config passwords → hashes, then strip password from public config served to clients. |
| E | Admin: Config editor should edit visibility flags in DB, not embed secrets in JSON (or only “set/rotate password” via secure endpoint). |
| F | View sessions: Already server-side; align RBAC so private content never leaks via allowedProjectIds without server checks for content routes. |
Risks to call out
- CDN caching: If folders config is cached, coordinate cache busting after migration.
- Offline/local dev: Keep a dev-only path or mock, or point to staging API.
- Cross-domain: Cookies must match
docs.gograb.space/ API subdomain policy; CORS already sensitive for docs-api.
6. Key files (quick map)
| Area | Path |
|---|---|
| Router / hash / initializer | apps/docs-angular/src/app/app.config.ts |
| Dynamic routes + view session routes | apps/docs-angular/src/app/services/dynamic-routes.service.ts |
| Static route definitions (legacy reference) | apps/docs-angular/src/app/app.routes.ts |
| Project list + view session URL parsing | apps/docs-angular/src/app/state/project-selection.state.ts |
| Private unlock + password match | apps/docs-angular/src/app/services/access.service.ts |
| View session entry redirect | apps/docs-angular/src/app/pages/view-session-entry/view-session-entry.component.ts |
| Admin view sessions UI | apps/docs-angular/src/app/admin/view-sessions/ |
| Folders config (repo copy) | apps/docs-angular/src/assets/docs-folders-config.json |
| Backend view sessions | APIs/backend-docs-api/src/app/view-sessions/ |
| Landing docs links | deploy/gograb-landing/index.html, deploy/gograb-landing/DEPLOY.md |
7. Explicitly out of scope for “landing-focused” work
- Implementing MongoDB or backend unlock APIs from the landing repo alone.
- Changing docs-angular auth without coordinating
backend-docs-apideploy and CORS.
Landing owner checklist (only)
- Docs buttons point to
https://docs.gograb.space/#/select-project(or a View Session URL from admin if curating projects). - Do not use relative
/docsfor static deploys that are not reverse-proxied to the docs app.
8. Related internal docs
docs/english/Docs-angular/docs-auth-implementation.md— auth patterns (may need update after server-side private unlock).docs/english/Docs-angular/plan-dynamic-docs-visibility.md— visibility (align with new model).
End of handoff. Next agent: pick up Phase A–B in backend-docs-api + schema repo, then wire AccessService in docs-angular.