docs: record auth profile flow

This commit is contained in:
rain
2026-07-11 09:36:02 +08:00
parent f60cc67749
commit 8a18202878
3 changed files with 496 additions and 4 deletions
@@ -2,10 +2,16 @@
创建时间:2026-07-09 15:14:58 +08:00 创建时间:2026-07-09 15:14:58 +08:00
接口依据:`genealogy-pc-openapi.yaml` 接口依据:`genealogy-pc-openapi.yaml`
接口基础地址:`http://test-genealogy-api.ddxcjp.cn` 接口基础地址:`http://182.61.18.23:8080`
旧依据处理:`APP.openapi.json` 只作为历史误用记录,不再作为 PC 页面继续对接依据。 旧依据处理:`APP.openapi.json` 只作为历史误用记录,不再作为 PC 页面继续对接依据。
旧进度记录:`docs/api-page-integration-tracker-2026-07-09.md` 旧进度记录:`docs/api-page-integration-tracker-2026-07-09.md`
## 当前地址契约
- 运行时唯一来源:根目录 `config.js`
- 当前开发和生产地址:`http://182.61.18.23:8080`
- 地址变更记录:2026-07-11 已由历史测试域名切换为当前 IP 和端口;文档中出现的 `test-genealogy-api.ddxcjp.cn` 仅用于描述历史事件,不代表当前运行时配置。
## 执行规则 ## 执行规则
1. 所有 PC 接口对接必须先进入本追踪表,再改代码。 1. 所有 PC 接口对接必须先进入本追踪表,再改代码。
@@ -29,7 +35,7 @@
分析文件:`genealogy-pc-openapi.yaml` 分析文件:`genealogy-pc-openapi.yaml`
1. `paths` 中实际存在 25 个接口操作,分为验证码、PC 认证、PC 文件、行政区划四类。 1. `paths` 中实际存在 25 个接口操作,分为验证码、PC 认证、PC 文件、行政区划四类。
2. `servers` 仍是本地地址示例,项目实际对接基础地址继续按用户指定使用 `https://test-genealogy-api.ddxcjp.cn` 2. `servers` 仍是本地地址示例;当前运行时基础地址以 `config.js` 为准,为 `http://182.61.18.23:8080`
3. 登录后接口使用 `Authorization` 作为 token header,同时所有 PC 认证和文件接口都要求 header `clientid`;用户最新提供的 PC `clientid``ced7e5f0498645c6ec642dcf450b036f`,客户端 Key 为 `web_pc` 3. 登录后接口使用 `Authorization` 作为 token header,同时所有 PC 认证和文件接口都要求 header `clientid`;用户最新提供的 PC `clientid``ced7e5f0498645c6ec642dcf450b036f`,客户端 Key 为 `web_pc`
4. `components.tags``components.schemas/requestBodies` 中出现家谱、动态、世系、字辈等业务模型,但 `paths` 没有对应接口路径;实现时不能把这些 schema 当成可调用 PC 接口。 4. `components.tags``components.schemas/requestBodies` 中出现家谱、动态、世系、字辈等业务模型,但 `paths` 没有对应接口路径;实现时不能把这些 schema 当成可调用 PC 接口。
5. 验证码 schema 示例里仍出现 `APP_LOGIN``PC_LOGIN` 等文本示例;实际页面场景以后台配置为准,当前明确可用的 PC/H5 场景为 `WEB_H5_LOGIN``WEB_H5_REGISTER``WEB_H5_FORGOT_PASSWORD` 5. 验证码 schema 示例里仍出现 `APP_LOGIN``PC_LOGIN` 等文本示例;实际页面场景以后台配置为准,当前明确可用的 PC/H5 场景为 `WEB_H5_LOGIN``WEB_H5_REGISTER``WEB_H5_FORGOT_PASSWORD`
@@ -67,7 +73,7 @@
| PC-007 | 复核通过 | 实施规划 | `genealogy-pc-openapi.yaml` | 当前计划与 YAML `paths` 一致,不使用旧 APP 路径 fallback。 | | PC-007 | 复核通过 | 实施规划 | `genealogy-pc-openapi.yaml` | 当前计划与 YAML `paths` 一致,不使用旧 APP 路径 fallback。 |
| PC-008 | 复核通过 | PC YAML 未覆盖业务页面 | `PC_API_NOT_AVAILABLE` | `utils/ApiClient.js` 统一抛 `PC_API_NOT_AVAILABLE`,旧 `/genealogy/app/` 请求路径扫描无结果。 | | PC-008 | 复核通过 | PC YAML 未覆盖业务页面 | `PC_API_NOT_AVAILABLE` | `utils/ApiClient.js` 统一抛 `PC_API_NOT_AVAILABLE`,旧 `/genealogy/app/` 请求路径扫描无结果。 |
| PC-009 | 本地复核通过 | 登录、注册、找回密码 | PC auth、`/captcha/*` | 三页场景编码、表单契约、Axios 请求客户端和相关测试均通过;真实账号流程待业务数据联调。 | | PC-009 | 本地复核通过 | 登录、注册、找回密码 | PC auth、`/captcha/*` | 三页场景编码、表单契约、Axios 请求客户端和相关测试均通过;真实账号流程待业务数据联调。 |
| PC-010 | 复核通过(网关可达 | `config.js``utils/ApiClient.js` | 测试 API 基础地址 | 开发地址为 `http://test-genealogy-api.ddxcjp.cn`2026-07-10 10:02:48 +08:00 外部 `curl.exe -I` 返回 `HTTP 200 OK`。 | | PC-010 | 复核(当前地址已同步 | `config.js``tests/config.test.js``utils/ApiClient.js` | API 基础地址 | 当前开发和生产地址`http://182.61.18.23:8080`;地址唯一运行时来源为 `config.js``tests/config.test.js` 已同步断言。 |
| PC-011 | 本地复核通过 | 三张认证页 TAC 弹窗 | `public/tac``/captcha/*` | 页面级挂载、移动端约束和结构测试通过;未修改 `tac.min.js`。 | | PC-011 | 本地复核通过 | 三张认证页 TAC 弹窗 | `public/tac``/captcha/*` | 页面级挂载、移动端约束和结构测试通过;未修改 `tac.min.js`。 |
## PC 页面覆盖矩阵草案 ## PC 页面覆盖矩阵草案
@@ -291,3 +297,15 @@
- 修改文件:`public/js/captcha-pages.js``tests/captcha-pages.test.js``docs/superpowers/plans/2026-07-10-tac-layer-real-mount-fix.md``docs/pc-api-page-integration-tracker-2026-07-09.md` - 修改文件:`public/js/captcha-pages.js``tests/captcha-pages.test.js``docs/superpowers/plans/2026-07-10-tac-layer-real-mount-fix.md``docs/pc-api-page-integration-tracker-2026-07-09.md`
- 修改结果:`createCaptchaLayer` 现在用字符串 `content` 让 Layui 创建 `<div data-captcha-layer-box="..."></div>`,弹层打开后再通过 `document.querySelector` 获取这个实际节点,并将它作为 TAC 的 `bindEl`。未修改 `public/tac`,未新增验证码 CSS,未传 TAC 视觉配置。 - 修改结果:`createCaptchaLayer` 现在用字符串 `content` 让 Layui 创建 `<div data-captcha-layer-box="..."></div>`,弹层打开后再通过 `document.querySelector` 获取这个实际节点,并将它作为 TAC 的 `bindEl`。未修改 `public/tac`,未新增验证码 CSS,未传 TAC 视觉配置。
- 验证结果:先运行 `node tests\captcha-pages.test.js` 复现失败;修复后 `node tests\auth-page-structure.test.js``node tests\captcha-pages.test.js``node --check public\js\captcha-pages.js``git diff --check` 通过。`git diff --check` 仅输出既有 CRLF 行尾提示,没有空白错误。 - 验证结果:先运行 `node tests\captcha-pages.test.js` 复现失败;修复后 `node tests\auth-page-structure.test.js``node tests\captcha-pages.test.js``node --check public\js\captcha-pages.js``git diff --check` 通过。`git diff --check` 仅输出既有 CRLF 行尾提示,没有空白错误。
## PC-025 注册、登录到个人资料闭环
- 状态:已完成
- 完成时间:2026-07-11 09:32:35 +08:00
- 规划文件:`docs/superpowers/specs/2026-07-11-auth-to-profile-flow-design.md`
- 页面范围:`register.html``login.html``profile.html``profile-data.html`
- 接口范围:`/genealogy/pc/auth/register``/genealogy/pc/auth/login``/genealogy/pc/auth/login/sms``/genealogy/pc/auth/profile``/genealogy/pc/auth/logout`
- 地址契约:运行时唯一来源为 `config.js`;当前开发和生产地址均为 `http://182.61.18.23:8080`
- 流程结果:注册成功清除 token 并跳转 `login.html`;密码和短信登录必须取得 token 后跳转 `profile.html`;个人资料无 token 或收到 HTTP/业务 `401` 时清 token 并跳转 `index.html`;确认退出无论接口结果都清 token 并跳转 `index.html`
- 修改文件:`tests/config.test.js``tests/utils.test.js``utils/ApiClient.js``tests/api-client.test.js``public/js/profile-pages.js``public/js/profile-common.js``profile.html``tests/profile-pages.test.js``tests/profile-logout-structure.test.js`
- 验证结果:`node tests/config.test.js``node tests/utils.test.js``node tests/api-client.test.js``node tests/auth-pages.test.js``node tests/profile-pages.test.js``node tests/profile-logout-structure.test.js``node --check utils/ApiClient.js``node --check public/js/profile-pages.js``node --check public/js/profile-common.js` 和全量 Node 测试均通过。
@@ -0,0 +1,474 @@
# Auth To Profile Flow Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Complete the PC registration, login, profile, unauthorized, logout, and endpoint-address flow with one token owner and deterministic redirects.
**Architecture:** `config.js` remains the sole runtime owner of the API base address. `utils/ApiClient.js` owns token validation, persistence, and cleanup; `profile-pages.js` decides whether a profile request is allowed and redirects unauthenticated users to the homepage; `profile-common.js` delegates confirmed logout to the API client. The integration tracker records the current address and verified behavior only after verification commands complete.
**Tech Stack:** Browser JavaScript (UMD and jQuery), Axios, Node.js `assert` tests, static HTML, Markdown.
## Global Constraints
- The current API base address is `http://182.61.18.23:8080` for development and production, and `config.js` is its only runtime owner.
- Runtime-related tests use the same address; only documents explicitly marked historical may retain the former test domain.
- Successful registration clears `genealogy_auth_token` and redirects to `login.html`; it never persists a registration response token.
- Only successful password or SMS login with a nonempty response token persists `genealogy_auth_token` and redirects to `profile.html`.
- `profile.html` and `profile-data.html` redirect to `index.html` before a profile request when no token exists, and after HTTP or business `401` responses.
- Confirmed logout requests `/genealogy/pc/auth/logout`, clears the token regardless of the request outcome, and redirects to `index.html`.
- Do not add global Axios redirects, duplicate token storage in pages, alter API paths, or change password-reset, phone-change, account-deactivation, or profile pages that do not load the profile API.
---
### Task 1: Synchronize the configured API address test
**Files:**
- Modify: `tests/config.test.js:11-28`
- Modify: `tests/utils.test.js:31`
**Interfaces:**
- Consumes: `configFactory(...).getConfig()` and `getApiBaseUrl()` from `config.js`.
- Produces: a test that asserts the current `config.js` address for both environments.
- [ ] **Step 1: Confirm the existing address-contract test fails**
The current test contains these stale assertions:
```js
assert.deepStrictEqual(developmentConfig.getConfig(), {
environment: 'development',
apiBaseUrl: 'http://test-genealogy-api.ddxcjp.cn'
});
assert.strictEqual(productionConfig.getApiBaseUrl(), 'http://test-genealogy-api.ddxcjp.cn');
```
Run: `node tests/config.test.js`
Expected: failure because `config.js` already returns `http://182.61.18.23:8080`.
- [ ] **Step 2: Update the stale test expectations**
Replace the two expected URL values with:
```js
assert.deepStrictEqual(developmentConfig.getConfig(), {
environment: 'development',
apiBaseUrl: 'http://182.61.18.23:8080'
});
assert.strictEqual(productionConfig.getApiBaseUrl(), 'http://182.61.18.23:8080');
```
Replace the mocked requester address in `tests/utils.test.js` with:
```js
baseUrl: 'http://182.61.18.23:8080',
```
- [ ] **Step 3: Run the focused configuration test**
Run: `node tests/config.test.js`
Expected: `config tests passed`.
Run: `node tests/utils.test.js`
Expected: `utils tests passed`.
- [ ] **Step 4: Commit the address-test synchronization**
```powershell
git add -- tests/config.test.js tests/utils.test.js
git commit -m "test: sync configured api address"
```
### Task 2: Enforce login-token and logout-cleanup contracts
**Files:**
- Modify: `utils/ApiClient.js:52-60, 167-191, 270-274`
- Modify: `tests/api-client.test.js:83-177`
**Interfaces:**
- Consumes: `getTokenFromResponse(data)`, `setToken(token)`, `clearToken()`, and public `client.login`, `client.loginBySms`, and `client.logout` methods.
- Produces: `client.login(body)` and `client.loginBySms(body)` reject with `ApiError('登录响应缺少 token')` when their response has no token; `client.logout()` clears the configured token key before resolving or rejecting.
- [ ] **Step 1: Write failing API-client assertions**
Append this after the registration assertions and before `client.sendSmsCode(...)` in `tests/api-client.test.js`:
```js
const missingTokenStore = createStore();
const missingTokenClient = GenealogyApi.createClient({
baseUrl: 'http://182.61.18.23:8080',
clientId: 'client-x',
tenantId: 'tenant-x',
tokenKey: 'token-key',
tokenStore: missingTokenStore,
axiosInstance: {
request: async () => ({
status: 200,
data: { code: 200, data: {} }
})
}
});
await assert.rejects(
missingTokenClient.login({ phone: '13800000000', password: 'md5' }),
(error) => error.message === '登录响应缺少 token'
);
assert.strictEqual(missingTokenStore.getItem('token-key'), null);
store.setItem('token-key', 'logout-token');
await client.logout();
assert.strictEqual(calls[9].url, '/genealogy/pc/auth/logout');
assert.strictEqual(store.getItem('token-key'), null);
const failedLogoutStore = createStore({
'token-key': 'logout-token'
});
const failedLogoutClient = GenealogyApi.createClient({
baseUrl: 'http://182.61.18.23:8080',
clientId: 'client-x',
tenantId: 'tenant-x',
tokenKey: 'token-key',
tokenStore: failedLogoutStore,
axiosInstance: {
request: async () => {
throw new Error('logout failed');
}
}
});
await assert.rejects(failedLogoutClient.logout(), /logout failed/);
assert.strictEqual(failedLogoutStore.getItem('token-key'), null);
```
Move the existing SMS-code assertions from `calls[9]` to `calls[10]` and change the final call-count assertion from `10` to `11`.
Replace the two existing `baseUrl: 'https://test-genealogy-api.ddxcjp.cn'` fixtures in this file with:
```js
baseUrl: 'http://182.61.18.23:8080',
```
- [ ] **Step 2: Run the focused API-client test and confirm failure**
Run: `node tests/api-client.test.js`
Expected: failure at the missing-token rejection because the current login method resolves without writing a token, before reaching the logout assertions.
- [ ] **Step 3: Add the minimal token validation and logout cleanup**
Add this helper after `getTokenFromResponse` in `utils/ApiClient.js`:
```js
function requireLoginToken(data) {
var token = getTokenFromResponse(data);
if (!token) throw new ApiError('登录响应缺少 token');
return token;
}
```
Replace the token writes in `login()` and `loginBySms()` with:
```js
setToken(requireLoginToken(data));
```
Replace `logout` with:
```js
logout: async function () {
try {
return await request('DELETE', '/genealogy/pc/auth/logout');
} finally {
clearToken();
}
},
```
- [ ] **Step 4: Run the API-client test and confirm all token paths pass**
Run: `node tests/api-client.test.js`
Expected: `api-client tests passed`.
- [ ] **Step 5: Commit the API-client contract**
```powershell
git add -- utils/ApiClient.js tests/api-client.test.js
git commit -m "fix: complete auth token lifecycle"
```
### Task 3: Guard profile access and connect confirmed logout
**Files:**
- Modify: `public/js/profile-pages.js:18-22, 165-198`
- Modify: `public/js/profile-common.js:9-82`
- Modify: `profile.html:80, 355`
- Modify: `tests/profile-pages.test.js:1-65`
- Create: `tests/profile-logout-structure.test.js`
**Interfaces:**
- Consumes: public `api.getToken()`, `api.clearToken()`, `api.currentProfile()`, `api.updateProfile()`, and `api.logout()` methods.
- Produces: `ProfilePages.shouldRedirectToHome(api, error)` for token and unauthorized classification; profile reads and writes redirect to `index.html` when that helper returns true; the existing logout controls call `api.logout()` before navigating to `index.html`.
- [ ] **Step 1: Write failing profile and logout tests**
Add these assertions before the final `console.log` in `tests/profile-pages.test.js`:
```js
assert.strictEqual(ProfilePages.shouldRedirectToHome({
getToken: () => ''
}), true);
assert.strictEqual(ProfilePages.shouldRedirectToHome({
getToken: () => 'token-x'
}), false);
assert.strictEqual(ProfilePages.shouldRedirectToHome({
getToken: () => 'token-x'
}, { status: 401 }), true);
assert.strictEqual(ProfilePages.shouldRedirectToHome({
getToken: () => 'token-x'
}, { code: 401 }), true);
assert.strictEqual(ProfilePages.shouldRedirectToHome({
getToken: () => 'token-x'
}, { status: 500 }), false);
```
Create `tests/profile-logout-structure.test.js` with:
```js
const assert = require('assert');
const fs = require('fs');
const path = require('path');
const profileHtml = fs.readFileSync(path.join(__dirname, '..', 'profile.html'), 'utf8');
const profileCommon = fs.readFileSync(path.join(__dirname, '..', 'public', 'js', 'profile-common.js'), 'utf8');
assert.match(profileHtml, /data-logout-confirm/);
assert.match(profileHtml, /<a class="btn primary magnetic" href="index\.html" data-logout-confirm>/);
assert.match(profileCommon, /function performLogout\(targetUrl\)/);
assert.match(profileCommon, /api\.logout\(\)/);
assert.match(profileCommon, /targetUrl \|\| 'index\.html'/);
console.log('profile logout structure tests passed');
```
- [ ] **Step 2: Run the new focused tests and confirm failure**
Run: `node tests/profile-pages.test.js`
Expected: failure because `shouldRedirectToHome` is not exported.
Run: `node tests/profile-logout-structure.test.js`
Expected: failure because the logout confirmation markup and `performLogout` function do not exist.
- [ ] **Step 3: Add profile token guard and unauthorized redirect**
Add these helpers after `getApi()` in `public/js/profile-pages.js`:
```js
function shouldRedirectToHome(api, error) {
var status = error && (error.status || error.code);
return !api || !api.getToken || !api.getToken() || Number(status) === 401;
}
function redirectToHome() {
if (!root.location) return;
if (typeof root.location.replace === 'function') {
root.location.replace('index.html');
return;
}
root.location.href = 'index.html';
}
function redirectUnauthorized(api, error) {
if (!shouldRedirectToHome(api, error)) return false;
if (api && api.clearToken) api.clearToken();
redirectToHome();
return true;
}
```
Replace the existing combined early-return condition in `loadProfile()` with these two branches:
```js
if (!api || !documentRef || !documentRef.querySelector('[data-profile-page]')) return;
if (redirectUnauthorized(api)) return;
```
Update its `catch` block to start with:
```js
if (redirectUnauthorized(api, error)) return;
```
Update `submitProfileForm()` to place `if (redirectUnauthorized(api)) return;` after its existing null guard, and to start its `catch` block with `if (redirectUnauthorized(api, error)) return;` before setting an error status or message.
Export the classifier with the existing public methods:
```js
shouldRedirectToHome: shouldRedirectToHome,
```
- [ ] **Step 4: Connect both logout confirmations to the API client**
Add this function before `bindLogout()` in `public/js/profile-common.js`:
```js
function performLogout(targetUrl) {
var api = window.GenealogyApi && window.GenealogyApi.defaultClient;
var redirect = function () {
window.location.href = targetUrl || 'index.html';
};
if (!api || !api.logout) {
redirect();
return;
}
api.logout().catch(function () {}).then(redirect);
}
```
In `bindLogout()`, change the default target URL to `index.html`, replace the Layui confirmation callback body with `performLogout(targetUrl);`, and add this event handler before the existing `[data-logout-close]` handler:
```js
$(document).on('click', '[data-logout-confirm]', function (event) {
event.preventDefault();
closeLegacyLogout();
performLogout($(this).attr('href') || 'index.html');
});
```
In `profile.html`, change the legacy confirmation anchor to:
```html
<a class="btn primary magnetic" href="index.html" data-logout-confirm>确认退出</a>
```
- [ ] **Step 5: Run the focused profile tests and syntax checks**
Run: `node tests/profile-pages.test.js`
Expected: `profile-pages tests passed`.
Run: `node tests/profile-logout-structure.test.js`
Expected: `profile logout structure tests passed`.
Run: `node --check public/js/profile-pages.js`
Expected: exit code `0`.
Run: `node --check public/js/profile-common.js`
Expected: exit code `0`.
- [ ] **Step 6: Commit the profile and logout flow**
```powershell
git add -- public/js/profile-pages.js public/js/profile-common.js profile.html tests/profile-pages.test.js tests/profile-logout-structure.test.js
git commit -m "fix: guard profile auth and logout"
```
### Task 4: Record the current flow and run end-to-end regression checks
**Files:**
- Modify: `docs/pc-api-page-integration-tracker-2026-07-09.md:1-9, 32, 70, 163`
- Modify: `docs/superpowers/specs/2026-07-11-auth-to-profile-flow-design.md:3-5`
**Interfaces:**
- Consumes: the verified results of Tasks 1 through 3.
- Produces: a tracker whose current address and authentication-flow status match the code and tests, and a spec marked approved for implementation.
- [ ] **Step 1: Run all focused flow tests**
Run:
```powershell
node tests/config.test.js
node tests/api-client.test.js
node tests/auth-pages.test.js
node tests/profile-pages.test.js
node tests/profile-logout-structure.test.js
```
Expected: each command prints its success message and exits with code `0`.
- [ ] **Step 2: Run syntax and complete regression checks**
Run:
```powershell
node --check utils/ApiClient.js
node --check public/js/profile-pages.js
node --check public/js/profile-common.js
Get-ChildItem -Path tests -Filter *.test.js | ForEach-Object { & node $_.FullName; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } }
```
Expected: all syntax checks exit `0`; every test script prints its success message; PowerShell exits `0` on the first test failure instead of masking it.
- [ ] **Step 3: Update the tracker from verified evidence**
At the top of `docs/pc-api-page-integration-tracker-2026-07-09.md`, replace the active base-address line with:
```markdown
接口基础地址:`http://182.61.18.23:8080`
```
Add this section immediately after the introductory historical-record lines:
```markdown
## Current Endpoint Contract
- Runtime owner: `config.js`.
- Current development and production address: `http://182.61.18.23:8080`.
- Address change record: on 2026-07-11 the active address changed from the historical test domain to this IP address and port. Historical references to `test-genealogy-api.ddxcjp.cn` do not describe the current runtime configuration.
```
Replace the YAML-analysis item that says the project currently uses the test domain with:
```markdown
2. `servers` 仍是本地地址示例;当前运行时基础地址以 `config.js` 为准,为 `http://182.61.18.23:8080`
```
Replace the PC-010 row with:
```markdown
| PC-010 | 已复核(当前地址已同步) | `config.js``tests/config.test.js``utils/ApiClient.js` | API 基础地址 | 当前开发和生产地址均为 `http://182.61.18.23:8080`;地址唯一运行时来源为 `config.js``tests/config.test.js` 已同步断言。 |
```
After Steps 1 and 2 pass, run `Get-Date -Format "yyyy-MM-dd HH:mm:ss K"` and insert its output as the `完成时间` line immediately after the `状态` line in this record. Append the rest of this record after the existing PC entries:
```markdown
## PC-025 注册、登录到个人资料闭环
- 状态:已完成
- 规划文件:`docs/superpowers/specs/2026-07-11-auth-to-profile-flow-design.md`
- 页面范围:`register.html``login.html``profile.html``profile-data.html`
- 接口范围:`/genealogy/pc/auth/register``/genealogy/pc/auth/login``/genealogy/pc/auth/login/sms``/genealogy/pc/auth/profile``/genealogy/pc/auth/logout`
- 地址契约:运行时唯一来源为 `config.js`;当前开发和生产地址均为 `http://182.61.18.23:8080`
- 流程结果:注册成功清除 token 并跳转 `login.html`;密码和短信登录必须取得 token 后跳转 `profile.html`;个人资料无 token 或收到 HTTP/业务 `401` 时清 token 并跳转 `index.html`;确认退出无论接口结果都清 token 并跳转 `index.html`
- 修改文件:`tests/config.test.js``utils/ApiClient.js``tests/api-client.test.js``public/js/profile-pages.js``public/js/profile-common.js``profile.html``tests/profile-pages.test.js``tests/profile-logout-structure.test.js`
- 验证结果:`node tests/config.test.js``node tests/api-client.test.js``node tests/auth-pages.test.js``node tests/profile-pages.test.js``node tests/profile-logout-structure.test.js`、三个 `node --check` 命令和全量 Node 测试均通过。
```
Change the spec status body to:
```markdown
Approved for implementation.
```
- [ ] **Step 4: Check final whitespace and commit the record**
Run: `git diff --check`
Expected: exit code `0`; pre-existing CRLF conversion warnings are not whitespace errors.
```powershell
git add -- docs/pc-api-page-integration-tracker-2026-07-09.md docs/superpowers/specs/2026-07-11-auth-to-profile-flow-design.md
git commit -m "docs: record auth profile flow"
```
@@ -2,7 +2,7 @@
## Status ## Status
Pending written-spec review. Approved for implementation.
## Goal ## Goal