docs: add consolidated dev URL reference and migrate /shop to /storefront
Some checks failed
CI / ruff (push) Successful in 10s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled

- Add Development URL Quick Reference section to url-routing overview
  with all login URLs, entry points, and full examples
- Replace /shop/ path segments with /storefront/ across 50 docs files
- Update file references: shop_pages.py → storefront_pages.py,
  templates/shop/ → templates/storefront/, api/v1/shop/ → api/v1/storefront/
- Preserve domain references (orion.shop) and /store/ staff dashboard paths
- Archive docs left unchanged (historical)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-25 13:23:44 +01:00
parent 3df75e2e78
commit d648c921b7
50 changed files with 1104 additions and 1049 deletions

View File

@@ -25,8 +25,8 @@
The Orion platform uses a **context-based authentication system** with three isolated security domains:
- **Admin Portal** - Platform administration and management
- **Store Portal** - Multi-tenant shop management
- **Customer Shop** - Public storefront and customer accounts
- **Store Portal** - Multi-tenant storefront management
- **Customer Storefront** - Public storefront and customer accounts
Each context uses **dual authentication** supporting both cookie-based (for HTML pages) and header-based (for API calls) authentication with complete isolation between contexts.
@@ -92,12 +92,12 @@ Each authentication context uses a separate cookie with path restrictions:
|----------|------------------|-------------|--------------|
| Admin | `admin_token` | `/admin` | Admin routes only |
| Store | `store_token` | `/store` | Store routes only |
| Customer | `customer_token` | `/shop` | Shop routes only |
| Customer | `customer_token` | `/storefront` | Storefront routes only |
**Browser Behavior:**
- When requesting `/admin/*`, browser sends `admin_token` cookie only
- When requesting `/store/*`, browser sends `store_token` cookie only
- When requesting `/shop/*`, browser sends `customer_token` cookie only
- When requesting `/storefront/*`, browser sends `customer_token` cookie only
This prevents cookie leakage between contexts.
@@ -157,7 +157,7 @@ Set-Cookie: admin_token=<JWT>; Path=/admin; HttpOnly; Secure; SameSite=Lax
**Role:** `store`
**Cookie:** `store_token` (path=/store)
**Purpose:** Store shop management, product catalog, orders, team management.
**Purpose:** Store management, product catalog, orders, team management.
**Access Control:**
- ❌ Admin users blocked (admins use admin portal for store management)
@@ -205,24 +205,24 @@ Set-Cookie: store_token=<JWT>; Path=/store; HttpOnly; Secure; SameSite=Lax
### 3. Customer Context
**Routes:** `/shop/account/*` (authenticated), `/shop/*` (public)
**Routes:** `/storefront/account/*` (authenticated), `/storefront/*` (public)
**Role:** `customer`
**Cookie:** `customer_token` (path=/shop)
**Cookie:** `customer_token` (path=/storefront)
**Purpose:** Product browsing (public), customer accounts, orders, profile management.
**Important - URL Pattern Context:**
The `/shop/*` routes work differently depending on deployment mode:
- **Subdomain Mode** (Production): `https://store.platform.com/shop/products`
- **Custom Domain** (Production): `https://customdomain.com/shop/products`
- **Path-Based** (Development): `http://localhost:8000/stores/{store_code}/shop/products`
The `/storefront/*` routes work differently depending on deployment mode:
- **Subdomain Mode** (Production): `https://store.platform.com/storefront/products`
- **Custom Domain** (Production): `https://customdomain.com/storefront/products`
- **Path-Based** (Development): `http://localhost:8000/storefront/{store_code}/products`
In path-based development mode, the full URL includes the store code (e.g., `/stores/acme/shop/products`), but the routes are still defined as `/shop/*` internally. See [URL Routing Guide](../architecture/url-routing/overview.md) for details.
In path-based development mode, the full URL includes the store code (e.g., `/storefront/acme/products`), but the routes are still defined as `/storefront/*` internally. See [URL Routing Guide](../architecture/url-routing/overview.md) for details.
**Access Control:**
- **Public Routes** (`/shop/products`, `/shop/cart`, etc.):
- **Public Routes** (`/storefront/products`, `/storefront/cart`, etc.):
- ✅ Anyone can access (no authentication)
- **Account Routes** (`/shop/account/*`):
- **Account Routes** (`/storefront/account/*`):
- ❌ Admin users blocked
- ❌ Store users blocked
- ✅ Customer users only
@@ -256,7 +256,7 @@ curl -X POST http://localhost:8000/api/v1/platform/stores/1/customers/login \
Additionally, sets cookie:
```
Set-Cookie: customer_token=<JWT>; Path=/shop; HttpOnly; Secure; SameSite=Lax
Set-Cookie: customer_token=<JWT>; Path=/storefront; HttpOnly; Secure; SameSite=Lax
```
---
@@ -323,13 +323,13 @@ async def store_dashboard(
})
# Customer account page
@router.get("/shop/account/dashboard", response_class=HTMLResponse)
@router.get("/storefront/account/dashboard", response_class=HTMLResponse)
async def customer_dashboard(
request: Request,
current_user: User = Depends(get_current_customer_from_cookie_or_header),
db: Session = Depends(get_db)
):
return templates.TemplateResponse("shop/account/dashboard.html", {
return templates.TemplateResponse("storefront/account/dashboard.html", {
"request": request,
"user": current_user
})
@@ -375,7 +375,7 @@ def create_product(
return {"message": "Product created"}
# Customer API
@router.post("/api/v1/shop/orders")
@router.post("/api/v1/storefront/orders")
def create_order(
order_data: OrderCreate,
current_user: User = Depends(get_current_customer_api),
@@ -389,10 +389,10 @@ def create_order(
Simply don't use any authentication dependency:
```python
@router.get("/shop/products")
@router.get("/storefront/products")
async def public_products(request: Request):
# No authentication required
return templates.TemplateResponse("shop/products.html", {
return templates.TemplateResponse("storefront/products.html", {
"request": request
})
```
@@ -498,7 +498,7 @@ def get_orders(
**Security Features:**
- **Token type validation:** Only accepts tokens with `type: "customer"` - admin and store tokens are rejected
- **Store validation:** Validates that `token.store_id` matches `request.state.store.id` (URL-based store)
- Prevents cross-store token reuse (customer from Store A cannot use token on Store B's shop)
- Prevents cross-store token reuse (customer from Store A cannot use token on Store B's storefront)
**Usage:**
```python
@@ -637,23 +637,23 @@ async def store_login_page(
```python
from models.database.customer import Customer
# Shop login page redirect
@router.get("/shop/account/login")
async def customer_login_page(
# Storefront login page redirect
@router.get("/storefront/account/login")
async def storefront_login_page(
request: Request,
customer: Customer | None = Depends(get_current_customer_optional)
):
if customer:
# Customer already logged in, redirect to account page
return RedirectResponse(url="/shop/account", status_code=302)
return RedirectResponse(url="/storefront/account", status_code=302)
# Not logged in, show login form
return templates.TemplateResponse("shop/login.html", {"request": request})
return templates.TemplateResponse("storefront/login.html", {"request": request})
```
**Use Cases:**
- Login pages (redirect if already authenticated)
- Public shop pages with conditional customer content (e.g., "My Orders" link)
- Public storefront pages with conditional customer content (e.g., "My Orders" link)
- Root redirects based on authentication status
---
@@ -744,7 +744,7 @@ All login endpoints return:
Additionally, the response sets an HTTP-only cookie:
- Admin: `admin_token` (path=/admin)
- Store: `store_token` (path=/store)
- Customer: `customer_token` (path=/shop)
- Customer: `customer_token` (path=/storefront)
---
@@ -752,7 +752,7 @@ Additionally, the response sets an HTTP-only cookie:
### Role-Based Access Control Matrix
| User Role | Admin Portal | Store Portal | Shop Catalog | Customer Account |
| User Role | Admin Portal | Store Portal | Storefront Catalog | Customer Account |
|-----------|--------------|---------------|--------------|------------------|
| Admin | ✅ Full | ❌ Blocked | ✅ View | ❌ Blocked |
| Store | ❌ Blocked | ✅ Full | ✅ View | ❌ Blocked |
@@ -863,7 +863,7 @@ Custom exceptions (such as those raised for missing claims) are preserved with t
4. **Test navigation:**
- Navigate to `/admin/dashboard` - Should work ✅
- Navigate to `/store/TESTSTORE/dashboard` - Should fail (cookie not sent) ❌
- Navigate to `/shop/account/dashboard` - Should fail (cookie not sent) ❌
- Navigate to `/storefront/account/dashboard` - Should fail (cookie not sent) ❌
5. **Logout:**
```
@@ -886,23 +886,23 @@ Custom exceptions (such as those raised for missing claims) are preserved with t
4. **Test navigation:**
- Navigate to `/store/{STORE_CODE}/dashboard` - Should work ✅
- Navigate to `/admin/dashboard` - Should fail ❌
- Navigate to `/shop/account/dashboard` - Should fail ❌
- Navigate to `/storefront/account/dashboard` - Should fail ❌
#### Test Customer Authentication
1. **Navigate to customer login:**
```
http://localhost:8000/shop/account/login
http://localhost:8000/storefront/account/login
```
2. **Login with customer credentials**
3. **Verify cookie in DevTools:**
- Look for `customer_token` cookie
- Verify `Path` is `/shop`
- Verify `Path` is `/storefront`
4. **Test navigation:**
- Navigate to `/shop/account/dashboard` - Should work ✅
- Navigate to `/storefront/account/dashboard` - Should work ✅
- Navigate to `/admin/dashboard` - Should fail ❌
- Navigate to `/store/{CODE}/dashboard` - Should fail ❌
@@ -955,7 +955,7 @@ curl -X POST http://localhost:8000/api/v1/platform/stores/1/customers/login \
-d '{"username":"customer","password":"customer123"}'
# Test authenticated endpoint with token
curl http://localhost:8000/api/v1/shop/orders \
curl http://localhost:8000/api/v1/storefront/orders \
-H "Authorization: Bearer <customer_access_token>"
# Test cross-context blocking
@@ -1101,8 +1101,8 @@ Admins should not log into store portal as this violates security boundaries.
**Symptom:** Customer trying to access management interfaces
**Explanation:** Customers only have access to:
- Public shop routes: `/shop/products`, etc.
- Their account: `/shop/account/*`
- Public storefront routes: `/storefront/products`, etc.
- Their account: `/storefront/account/*`
Admin and store portals are not accessible to customers.
@@ -1169,7 +1169,7 @@ Look for:
2. **Don't mix authentication contexts:**
- Admin users should use admin portal
- Store users should use store portal
- Customers should use shop
- Customers should use storefront
3. **Always check user.is_active:**
```python