diff --git a/AGENTS.md b/AGENTS.md index 58401a1..58c12e9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -37,6 +37,7 @@ project-root/ │ └── utils/ # 工具函数 ├── internal/ │ ├── handler/ # HTTP 路由层(仅参数校验 + 调用 service) +│ ├── router/ # 路由注册层(集中记录并注册所有 HTTP/WS 路由) │ ├── service/ # 业务逻辑层 │ ├── domain/ # 领域模型(所有共享类型定义在此) │ ├── storage/ # 存储层(postgres / redis / s3 / milvus / es) @@ -71,6 +72,31 @@ project-root/ - 所有 API 响应格式:`{ "success": true, "data": {}, "error": null }` - 敏感信息只从环境变量读取,禁止硬编码 +### 后端路由规范 +- 路由注册统一收敛在 `internal/router` 包:只在这里出现 `Group/GET/POST/...` 等路由声明 +- `handler.NewServer` 只负责初始化 Hertz + 组装依赖并调用 `router.Register(...)`,不要在 `handler/handler.go` 内直接写路由 +- 模块拆分规则: + - `internal/router/router.go`:总入口(创建 `/v1` 分组、串联各模块注册) + - `internal/router/.go`:按模块注册路由(例如 `auth.go`、`resume.go`、`interview.go`) + - `internal/handler/.go`:实现具体 handler 方法(参数校验 + 调用 service),不做路由声明 +- 路由分层约定: + - 公开路由:`/`、`/health`、`/healthz`、`/v1/auth/*`、`/v1/device/check` + - 受保护路由:`/v1/resume/*`、`/v1/interview/*`(HTTP)、`/v1/report/*`、`/v1/questionnaire/*` 统一挂 JWT 中间件 + - WebSocket 路由:`/v1/interview/ws/:interview_id` 不挂 JWT 中间件(见下文原因),鉴权在握手阶段完成 +- WebSocket 鉴权与安全要求: + - 浏览器原生 WebSocket API 不支持自定义 header,因此 WS 路由鉴权逻辑必须在握手阶段实现 + - token 获取顺序:优先 `Authorization: Bearer `,为空再读取 query 参数 `token=` + - `CheckOrigin` 不允许长期保持“全放行”,生产环境需按配置白名单校验来源 +- 限流约定(保持 key 与维度一致,便于观测与压测): + - `/v1/resume/parse`:IP + USER 双维度限流,key 为 `resume.parse` + - `/v1/questionnaire/submit`:IP + USER 双维度限流,key 为 `questionnaire.submit` + - WS 握手:IP + USER 双维度限流,连接建立相比普通 HTTP 可更宽松,但必须保留限流 +- 新增/调整接口的必做项: + - 在 `internal/router` 增补或修改路由声明,并按模块归档到对应文件 + - 同步更新 `docu/api.md` 的接口定义与 curl 示例,避免文档与实现漂移 + - 变更接口语义/响应结构时同步更新前端调用与相关测试 + - 避免引入 import cycle:`internal/router` 不应依赖 `internal/handler`(路由层通过 `router.Deps` 以接口方式接收 handler 实例) + ### 前端规范 - 组件使用函数式写法,禁止 class 组件 - Props 必须有 TypeScript interface 类型定义 diff --git a/docu/api.md b/docu/api.md new file mode 100644 index 0000000..2769e4b --- /dev/null +++ b/docu/api.md @@ -0,0 +1,853 @@ +# AI Interview API + +本文档按模块整理 HTTP API,并为每个接口提供入参/出参字段说明与可直接测试的 curl。 + +## 约定 + +- Base URL: `https://api.aiinterview.com/v1` +- 文档中接口路径不带 `/v1` 前缀(例如 `POST /auth/login`),实际请求请使用 `Base URL + Path` +- 认证:默认需要 `Authorization: Bearer {jwt_token}`,个别接口在说明中标注为“无需登录” +- 入参: + - `POST` 默认 `Content-Type: application/json`,请求体为 JSON + - `GET` 使用 Query 参数 + - 例外:文件/音频上传接口按各自章节的 `Content-Type` 执行 +- 统一响应体(所有接口): + +成功: + +```json +{ + "success": true, + "data": {}, + "error": null +} +``` + +失败: + +```json +{ + "success": false, + "data": null, + "error": { + "code": 1001, + "message": "参数错误", + "request_id": "req_123" + } +} +``` + +## 认证模块 + +### 注册 + +- Method: `POST` +- Path: `/auth/register` +- Auth: 无需登录 +- Content-Type: `application/json` + +**入参(JSON Body)** + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| username | string | 是 | 用户名 | `张三` | +| email | string | 是 | 邮箱 | `zhangsan@example.com` | +| password | string | 是 | 密码 | `xxxxxxxx` | + +**出参(data)** + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| user_id | string | 是 | 用户 ID | `uuid` | +| username | string | 是 | 用户名 | `张三` | +| token | string | 是 | JWT | `jwt_token` | + +**curl** + +```bash +curl -sS -X POST 'https://api.aiinterview.com/v1/auth/register' \ + -H 'Content-Type: application/json' \ + -d '{ + "username": "张三", + "email": "zhangsan@example.com", + "password": "xxxxxxxx" + }' +``` + +### 登录 + +- Method: `POST` +- Path: `/auth/login` +- Auth: 无需登录 +- Content-Type: `application/json` + +**入参(JSON Body)** + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| email | string | 是 | 邮箱 | `zhangsan@example.com` | +| password | string | 是 | 密码 | `xxxxxxxx` | + +**出参(data)** + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| user_id | string | 是 | 用户 ID | `uuid` | +| username | string | 是 | 用户名 | `张三` | +| token | string | 是 | JWT | `jwt_token` | + +**curl** + +```bash +curl -sS -X POST 'https://api.aiinterview.com/v1/auth/login' \ + -H 'Content-Type: application/json' \ + -d '{ + "email": "zhangsan@example.com", + "password": "xxxxxxxx" + }' +``` + +### 游客模式 + +- Method: `POST` +- Path: `/auth/guest` +- Auth: 无需登录 +- Content-Type: `application/json` + +**入参(JSON Body)** + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| (空对象) | object | 是 | 固定传 `{}` | `{}` | + +**出参(data)** + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| user_id | string | 是 | 游客用户 ID | `guest_uuid` | +| token | string | 是 | JWT | `jwt_token` | +| expires_at | string | 是 | 过期时间(RFC3339) | `2024-01-02T10:00:00Z` | + +**curl** + +```bash +curl -sS -X POST 'https://api.aiinterview.com/v1/auth/guest' \ + -H 'Content-Type: application/json' \ + -d '{}' +``` + +## 设备检测模块 + +### 检测设备状态 + +- Method: `POST` +- Path: `/device/check` +- Auth: 需要登录 +- Content-Type: `application/json` + +**Headers** + +| Header | 必填 | 说明 | 示例 | +|---|---:|---|---| +| Authorization | 是 | `Bearer {jwt_token}` | `Bearer xxx` | + +**入参(JSON Body)** + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| has_microphone | boolean | 是 | 是否有麦克风权限 | `true` | +| has_camera | boolean | 是 | 是否有摄像头权限 | `true` | +| browser | string | 是 | 浏览器信息 | `Chrome 120` | +| os | string | 是 | 操作系统信息 | `Windows 11` | + +**出参(data)** + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| status | string | 是 | 设备状态 | `ready` | +| message | string | 是 | 提示信息 | `设备检测通过,可以开始面试` | + +**curl** + +```bash +curl -sS -X POST 'https://api.aiinterview.com/v1/device/check' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer jwt_token' \ + -d '{ + "has_microphone": true, + "has_camera": true, + "browser": "Chrome 120", + "os": "Windows 11" + }' +``` + +## 简历模块 + +### 解析简历(文件上传) + +- Method: `POST` +- Path: `/resume/parse` +- Auth: 需要登录 +- Content-Type: `multipart/form-data` + +**Headers** + +| Header | 必填 | 说明 | 示例 | +|---|---:|---|---| +| Authorization | 是 | `Bearer {jwt_token}` | `Bearer xxx` | + +**入参(Form)** + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| file | file | 是 | PDF 简历文件 | `resume.pdf` | + +**出参(data)** + +| 字段 | 类型 | 必填 | 说明 | +|---|---|---:|---| +| skills | string[] | 是 | 技能列表 | +| projects | object[] | 是 | 项目经历 | +| internships | object[] | 是 | 实习经历 | +| education | object | 是 | 教育信息 | + +`projects[]` 字段: + +| 字段 | 类型 | 必填 | 说明 | +|---|---|---:|---| +| name | string | 是 | 项目名称 | +| tech_stack | string[] | 是 | 技术栈 | +| description | string | 是 | 描述 | +| highlights | string[] | 是 | 亮点 | + +`internships[]` 字段: + +| 字段 | 类型 | 必填 | 说明 | +|---|---|---:|---| +| company | string | 是 | 公司 | +| position | string | 是 | 岗位 | +| duration | string | 是 | 时间区间 | + +`education` 字段: + +| 字段 | 类型 | 必填 | 说明 | +|---|---|---:|---| +| school | string | 是 | 学校 | +| major | string | 是 | 专业 | +| degree | string | 是 | 学历 | +| graduation | string | 是 | 毕业时间 | + +**curl** + +```bash +curl -sS -X POST 'https://api.aiinterview.com/v1/resume/parse' \ + -H 'Authorization: Bearer jwt_token' \ + -F 'file=@/path/to/resume.pdf' +``` + +### 提交简历信息 + +- Method: `POST` +- Path: `/resume/submit` +- Auth: 需要登录 +- Content-Type: `application/json` + +**Headers** + +| Header | 必填 | 说明 | 示例 | +|---|---:|---|---| +| Authorization | 是 | `Bearer {jwt_token}` | `Bearer xxx` | + +**入参(JSON Body)** + +| 字段 | 类型 | 必填 | 说明 | +|---|---|---:|---| +| user_id | string | 是 | 用户 ID | +| skills | string[] | 是 | 技能列表 | +| projects | object[] | 是 | 项目经历 | +| internships | object[] | 是 | 实习经历 | +| education | object | 是 | 教育信息 | + +`projects[] / internships[] / education` 字段同 “解析简历”章节。 + +**出参(data)** + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| resume_id | string | 是 | 简历 ID | `uuid` | +| message | string | 是 | 提示信息 | `简历信息保存成功` | + +**curl** + +```bash +curl -sS -X POST 'https://api.aiinterview.com/v1/resume/submit' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer jwt_token' \ + -d '{ + "user_id": "uuid", + "skills": ["Java", "Redis", "MySQL"], + "projects": [ + { + "name": "电商平台", + "tech_stack": ["SpringBoot", "Redis"], + "description": "负责订单模块开发", + "highlights": ["QPS提升3倍"] + } + ], + "internships": [ + { + "company": "字节跳动", + "position": "后端开发实习生", + "duration": "2023.06-2023.09" + } + ], + "education": { + "school": "xxx大学", + "major": "计算机科学与技术", + "degree": "本科", + "graduation": "2025-06" + } + }' +``` + +## 面试配置模块 + +### 选择面试岗位和方向 + +- Method: `POST` +- Path: `/interview/config` +- Auth: 需要登录 +- Content-Type: `application/json` + +**Headers** + +| Header | 必填 | 说明 | 示例 | +|---|---:|---|---| +| Authorization | 是 | `Bearer {jwt_token}` | `Bearer xxx` | + +**入参(JSON Body)** + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| user_id | string | 是 | 用户 ID | `uuid` | +| position | string | 是 | 岗位枚举 | `golang` | +| direction | string | 是 | 方向枚举 | `backend` | + +**position 枚举** + +| 值 | 说明 | +|---|---| +| golang | Golang开发 | +| java | Java开发 | +| frontend | 前端工程师 | +| test | 测试开发 | + +**direction 枚举** + +| 值 | 说明 | +|---|---| +| backend | 软件开发 | +| cloud | 云平台运维开发 | +| agent | Agent开发 | +| server | 服务端开发 | + +**出参(data)** + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| config_id | string | 是 | 配置 ID | `uuid` | +| message | string | 是 | 提示信息 | `配置保存成功` | + +**curl** + +```bash +curl -sS -X POST 'https://api.aiinterview.com/v1/interview/config' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer jwt_token' \ + -d '{ + "user_id": "uuid", + "position": "golang", + "direction": "backend" + }' +``` + +## 面试模块 + +### 创建面试 + +- Method: `POST` +- Path: `/interview/create` +- Auth: 需要登录 +- Content-Type: `application/json` + +**Headers** + +| Header | 必填 | 说明 | 示例 | +|---|---:|---|---| +| Authorization | 是 | `Bearer {jwt_token}` | `Bearer xxx` | + +**入参(JSON Body)** + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| user_id | string | 是 | 用户 ID | `uuid` | + +**出参(data)** + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| interview_id | string | 是 | 面试 ID | `uuid` | +| stage | string | 是 | 当前阶段 | `intro` | +| created_at | string | 是 | 创建时间(RFC3339) | `2024-01-01T10:00:00Z` | + +**curl** + +```bash +curl -sS -X POST 'https://api.aiinterview.com/v1/interview/create' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer jwt_token' \ + -d '{ + "user_id": "uuid" + }' +``` + +### 建立 SSE 连接 + +- Method: `GET` +- Path: `/interview/stream` +- Auth: 需要登录 +- Accept: `text/event-stream` + +**Query** + +| 参数 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| interview_id | string | 是 | 面试 ID | `uuid` | + +**curl** + +```bash +curl -N -sS 'https://api.aiinterview.com/v1/interview/stream?interview_id=uuid' \ + -H 'Accept: text/event-stream' \ + -H 'Authorization: Bearer jwt_token' +``` + +### 发送音频流(音频上传) + +- Method: `POST` +- Path: `/interview/audio` +- Auth: 需要登录 +- Content-Type: `application/octet-stream` + +**Headers** + +| Header | 必填 | 说明 | 示例 | +|---|---:|---|---| +| Authorization | 是 | `Bearer {jwt_token}` | `Bearer xxx` | +| X-Interview-Id | 是 | 当前面试 ID | `uuid` | +| X-Turn-Id | 是 | 当前轮次 ID | `uuid` | + +**入参(Body)** + +| 字段 | 类型 | 必填 | 说明 | +|---|---|---:|---| +| (raw) | bytes | 是 | 原始音频数据(PCM / WebM) | + +**出参(data)** + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| turn_id | string | 是 | 轮次 ID | `uuid` | +| status | string | 是 | 接收状态 | `received` | + +**curl** + +```bash +curl -sS -X POST 'https://api.aiinterview.com/v1/interview/audio' \ + -H 'Authorization: Bearer jwt_token' \ + -H 'Content-Type: application/octet-stream' \ + -H 'X-Interview-Id: uuid' \ + -H 'X-Turn-Id: uuid' \ + --data-binary '@/path/to/audio.bin' +``` + +### 结束面试 + +- Method: `POST` +- Path: `/interview/finish` +- Auth: 需要登录 +- Content-Type: `application/json` + +**Headers** + +| Header | 必填 | 说明 | 示例 | +|---|---:|---|---| +| Authorization | 是 | `Bearer {jwt_token}` | `Bearer xxx` | + +**入参(JSON Body)** + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| interview_id | string | 是 | 面试 ID | `uuid` | + +**出参(data)** + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| interview_id | string | 是 | 面试 ID | `uuid` | +| finished_at | string | 是 | 结束时间(RFC3339) | `2024-01-01T11:00:00Z` | +| duration_seconds | number | 是 | 面试时长(秒) | `3600` | + +**curl** + +```bash +curl -sS -X POST 'https://api.aiinterview.com/v1/interview/finish' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer jwt_token' \ + -d '{ + "interview_id": "uuid" + }' +``` + +### 查询面试状态 + +- Method: `GET` +- Path: `/interview/state` +- Auth: 需要登录 + +**Query** + +| 参数 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| interview_id | string | 是 | 面试 ID | `uuid` | + +**出参(data)** + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| interview_id | string | 是 | 面试 ID | `uuid` | +| stage | string | 是 | 当前阶段 | `questioning` | +| questions_asked | number | 是 | 已提问数量 | `3` | +| current_question_followups | number | 是 | 当前问题追问次数 | `1` | +| started_at | string | 是 | 开始时间(RFC3339) | `2024-01-01T10:00:00Z` | + +**stage 枚举** + +| 值 | 说明 | +|---|---| +| intro | 自我介绍阶段 | +| questioning | 技术提问阶段 | +| algorithm | 算法题阶段 | +| closing | 反问阶段 | +| finished | 面试结束 | + +**curl** + +```bash +curl -sS 'https://api.aiinterview.com/v1/interview/state?interview_id=uuid' \ + -H 'Authorization: Bearer jwt_token' +``` + +## 代码提交模块 + +### 提交代码 + +- Method: `POST` +- Path: `/interview/code/submit` +- Auth: 需要登录 +- Content-Type: `application/json` + +**Headers** + +| Header | 必填 | 说明 | 示例 | +|---|---:|---|---| +| Authorization | 是 | `Bearer {jwt_token}` | `Bearer xxx` | + +**入参(JSON Body)** + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| interview_id | string | 是 | 面试 ID | `uuid` | +| question_id | string | 是 | 题目 ID | `uuid` | +| language | string | 是 | 语言枚举 | `java` | +| code | string | 是 | 代码内容 | `class Solution {...}` | + +**language 枚举** + +| 值 | 说明 | +|---|---| +| java | Java | +| python | Python | +| go | Go | +| cpp | C++ | + +**出参(data)** + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| status | string | 是 | 状态 | `judging` | +| message | string | 是 | 提示信息 | `代码评估中` | + +**curl** + +```bash +curl -sS -X POST 'https://api.aiinterview.com/v1/interview/code/submit' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer jwt_token' \ + -d '{ + "interview_id": "uuid", + "question_id": "uuid", + "language": "java", + "code": "class Solution {\\n public int[] twoSum(int[] nums, int target) {\\n return null;\\n }\\n}" + }' +``` + +## 问卷模块 + +### 获取问卷(面试结束后) + +- Method: `GET` +- Path: `/questionnaire` +- Auth: 需要登录 + +**Query** + +| 参数 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| interview_id | string | 是 | 面试 ID | `uuid` | + +**出参(data)** + +| 字段 | 类型 | 必填 | 说明 | +|---|---|---:|---| +| interview_id | string | 是 | 面试 ID | +| turns | object[] | 是 | 轮次列表 | + +`turns[]` 字段: + +| 字段 | 类型 | 必填 | 说明 | +|---|---|---:|---| +| turn_id | string | 是 | 轮次 ID | +| stage | string | 是 | 阶段 | +| question | string | 是 | 问题 | +| user_answer | string | 是 | 用户回答文本 | + +**curl** + +```bash +curl -sS 'https://api.aiinterview.com/v1/questionnaire?interview_id=uuid' \ + -H 'Authorization: Bearer jwt_token' +``` + +### 提交问卷 + +- Method: `POST` +- Path: `/questionnaire/submit` +- Auth: 需要登录 +- Content-Type: `application/json` + +**Headers** + +| Header | 必填 | 说明 | 示例 | +|---|---:|---|---| +| Authorization | 是 | `Bearer {jwt_token}` | `Bearer xxx` | + +**入参(JSON Body)** + +| 字段 | 类型 | 必填 | 说明 | +|---|---|---:|---| +| interview_id | string | 是 | 面试 ID | +| answers | object[] | 是 | 答案列表 | + +`answers[]` 字段: + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| turn_id | string | 是 | 轮次 ID | `001` | +| quality | string | 是 | 质量枚举 | `good` | +| feedback | string | 否 | 反馈内容 | `追问很有启发` | + +**quality 枚举** + +| 值 | 说明 | +|---|---| +| good | 这轮对话质量好 | +| bad | 这轮对话质量差 | + +**出参(data)** + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| message | string | 是 | 提示信息 | `问卷提交成功,感谢你的反馈` | + +**curl** + +```bash +curl -sS -X POST 'https://api.aiinterview.com/v1/questionnaire/submit' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer jwt_token' \ + -d '{ + "interview_id": "uuid", + "answers": [ + { "turn_id": "001", "quality": "good", "feedback": "追问很有启发" }, + { "turn_id": "002", "quality": "bad", "feedback": "追问方向感觉不对" } + ] + }' +``` + +## 报告模块 + +### 查询报告状态 + +- Method: `GET` +- Path: `/report/status` +- Auth: 需要登录 + +**Query** + +| 参数 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| interview_id | string | 是 | 面试 ID | `uuid` | + +**出参(data)** + +| 字段 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| status | string | 是 | 状态枚举 | `generating` | +| message | string | 是 | 提示信息 | `报告生成中` | + +**status 枚举** + +| 值 | 说明 | +|---|---| +| pending | 等待生成 | +| generating | 生成中 | +| done | 生成完成 | +| failed | 生成失败 | + +**curl** + +```bash +curl -sS 'https://api.aiinterview.com/v1/report/status?interview_id=uuid' \ + -H 'Authorization: Bearer jwt_token' +``` + +### 获取报告 + +- Method: `GET` +- Path: `/report` +- Auth: 需要登录 + +**Query** + +| 参数 | 类型 | 必填 | 说明 | 示例 | +|---|---|---:|---|---| +| interview_id | string | 是 | 面试 ID | `uuid` | + +**出参(data)** + +| 字段 | 类型 | 必填 | 说明 | +|---|---|---:|---| +| interview_id | string | 是 | 面试 ID | +| dimensions | object | 是 | 维度评分 | +| summary | string | 是 | 总结 | +| strong_points | string[] | 是 | 优点 | +| weak_points | string[] | 是 | 不足 | +| created_at | string | 是 | 创建时间(RFC3339) | + +`dimensions` 字段: + +| 字段 | 类型 | 必填 | 说明 | +|---|---|---:|---| +| knowledge_depth | number | 是 | 知识深度 | +| expression | number | 是 | 表达能力 | +| problem_solving | number | 是 | 解决问题 | +| code_quality | number | 是 | 代码质量 | +| stress_response | number | 是 | 抗压表现 | + +**curl** + +```bash +curl -sS 'https://api.aiinterview.com/v1/report?interview_id=uuid' \ + -H 'Authorization: Bearer jwt_token' +``` + +## SSE 事件(面试实时推送) + +通过 `GET /interview/stream` 推送,基本格式: + +```text +event: {event_type} +data: {json_payload} +``` + +### text.delta + +```text +event: text.delta +data: {"turn_id":"uuid","delta":"你提到了"} +``` + +### text.done + +```text +event: text.done +data: {"turn_id":"uuid","full_text":"..."} +``` + +### audio.delta + +```text +event: audio.delta +data: {"turn_id":"uuid","audio_base64":"..."} +``` + +### audio.done + +```text +event: audio.done +data: {"turn_id":"uuid"} +``` + +### stage.changed + +```text +event: stage.changed +data: {"from":"intro","to":"questioning"} +``` + +### code.judged + +```text +event: code.judged +data: {"correctness":true,"time_complexity":"O(n)","space_complexity":"O(1)","issues":["..."]} +``` + +### resume.parsed + +```text +event: resume.parsed +data: {"status":"done"} +``` + +### report.ready + +```text +event: report.ready +data: {"interview_id":"uuid"} +``` + +### interview.finished + +```text +event: interview.finished +data: {"interview_id":"uuid","finished_at":"2024-01-01T11:00:00Z"} +``` + +### error + +```text +event: error +data: {"code":5001,"message":"ASR识别失败,请重试"} +``` + diff --git a/frontend/.npm-cache/_cacache/content-v2/sha512/00/90/dd60e767c910d5e5be80ae297308f3f07357a3907728c856abaa53ea4fbcd162385abdc4f7b92aea70cbec821d828283db2b7442c321da572c5870fd80ae b/frontend/.npm-cache/_cacache/content-v2/sha512/00/90/dd60e767c910d5e5be80ae297308f3f07357a3907728c856abaa53ea4fbcd162385abdc4f7b92aea70cbec821d828283db2b7442c321da572c5870fd80ae new file mode 100644 index 0000000..0ca4138 Binary files /dev/null and b/frontend/.npm-cache/_cacache/content-v2/sha512/00/90/dd60e767c910d5e5be80ae297308f3f07357a3907728c856abaa53ea4fbcd162385abdc4f7b92aea70cbec821d828283db2b7442c321da572c5870fd80ae differ diff --git a/frontend/.npm-cache/_cacache/content-v2/sha512/00/e2/2049009ea62258c0fdc04671b1fb95674eed870587736c63f8e5e2f0d6faf7cc1def64b7b279dd6c0bd8676dc39cf7f4ab33233944f42b906cf8692f59a3 b/frontend/.npm-cache/_cacache/content-v2/sha512/00/e2/2049009ea62258c0fdc04671b1fb95674eed870587736c63f8e5e2f0d6faf7cc1def64b7b279dd6c0bd8676dc39cf7f4ab33233944f42b906cf8692f59a3 new file mode 100644 index 0000000..c0d2bb7 Binary files /dev/null and b/frontend/.npm-cache/_cacache/content-v2/sha512/00/e2/2049009ea62258c0fdc04671b1fb95674eed870587736c63f8e5e2f0d6faf7cc1def64b7b279dd6c0bd8676dc39cf7f4ab33233944f42b906cf8692f59a3 differ diff --git a/frontend/.npm-cache/_cacache/content-v2/sha512/02/9e/86d16430714fcb1ecbcbc0e3757c0417f59a7403663a63f709065f6bfc96d6f74672838ff36c6eb3cca6b639300b10b6ab60798abb41a1a4ce443beed3d2 b/frontend/.npm-cache/_cacache/content-v2/sha512/02/9e/86d16430714fcb1ecbcbc0e3757c0417f59a7403663a63f709065f6bfc96d6f74672838ff36c6eb3cca6b639300b10b6ab60798abb41a1a4ce443beed3d2 new file mode 100644 index 0000000..c673633 Binary files /dev/null and b/frontend/.npm-cache/_cacache/content-v2/sha512/02/9e/86d16430714fcb1ecbcbc0e3757c0417f59a7403663a63f709065f6bfc96d6f74672838ff36c6eb3cca6b639300b10b6ab60798abb41a1a4ce443beed3d2 differ diff --git a/frontend/.npm-cache/_cacache/content-v2/sha512/03/5b/2b7b6ea47bb1c322e63f336de777d81f07e9eb9a1b58c8c20d6e3235cc727162d78a47aa92317e7a16c9a331c0dbdd231c8c983906245180e082ff2043d2 b/frontend/.npm-cache/_cacache/content-v2/sha512/03/5b/2b7b6ea47bb1c322e63f336de777d81f07e9eb9a1b58c8c20d6e3235cc727162d78a47aa92317e7a16c9a331c0dbdd231c8c983906245180e082ff2043d2 new file mode 100644 index 0000000..69f644c Binary files /dev/null and b/frontend/.npm-cache/_cacache/content-v2/sha512/03/5b/2b7b6ea47bb1c322e63f336de777d81f07e9eb9a1b58c8c20d6e3235cc727162d78a47aa92317e7a16c9a331c0dbdd231c8c983906245180e082ff2043d2 differ diff --git a/frontend/.npm-cache/_cacache/content-v2/sha512/03/8c/d1c017d36dd7ed8b455756ff26c41f8c63a490d546119a5656da86b41eaed2a285dbc857719d110d880fe68e3aa28caa5ccf38e3f61696331130f40b34aa b/frontend/.npm-cache/_cacache/content-v2/sha512/03/8c/d1c017d36dd7ed8b455756ff26c41f8c63a490d546119a5656da86b41eaed2a285dbc857719d110d880fe68e3aa28caa5ccf38e3f61696331130f40b34aa new file mode 100644 index 0000000..f942002 --- /dev/null +++ b/frontend/.npm-cache/_cacache/content-v2/sha512/03/8c/d1c017d36dd7ed8b455756ff26c41f8c63a490d546119a5656da86b41eaed2a285dbc857719d110d880fe68e3aa28caa5ccf38e3f61696331130f40b34aa @@ -0,0 +1 @@ +{"name":"brace-expansion","dist-tags":{"3.x":"3.0.1","2.x":"2.0.2","1.x":"1.1.12","maintenance-v3":"3.0.2","maintenance-v1":"1.1.15","latest":"5.0.6","maintenance-v2":"2.1.1"},"versions":{"0.0.0":{"name":"brace-expansion","version":"0.0.0","dependencies":{"concat-map":"0.0.0","balanced-match":"0.0.0"},"devDependencies":{"tape":"~1.1.1"},"dist":{"shasum":"b2142015e8ee12d4cdae2a23908d28d44c2baa9f","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-0.0.0.tgz","integrity":"sha512-ZjZtiom0CcPQjWOvuqQsl/jP/GbJYO9oRJwJiZcB0f2e4PM3EAwoxAzTJBOcUJ0SSlKShb0wB5bkpzoH4YgbYg==","signatures":[{"sig":"MEYCIQDIz68OppfZj5bE9pvkPOiULQUHgRnY5X0txTOV7vNCFQIhAI4tRdbxB4npUxcuFaodGaFxxqwJMGQt0kUIqjs5WvNq","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]}},"1.0.0":{"name":"brace-expansion","version":"1.0.0","dependencies":{"concat-map":"0.0.0","balanced-match":"^0.2.0"},"devDependencies":{"tape":"~1.1.1"},"dist":{"shasum":"a01656d12ebbbd067c8e935903f194ea5efee4ee","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.0.0.tgz","integrity":"sha512-lpqC6FxtM5XVWHdevRkMRPWSpsoLOWqurCALDPKm0VnLHf3DQ2rqFO8WBc6ierDnXeiMnCzwtDl6PgZrPY7xxA==","signatures":[{"sig":"MEUCIHiiZuTN8rlOZuQfGyNVObHLXk06S8FCymzz59nrA6kIAiEAkQNqXm+yIrcqfrgeOfchnIebTgu7lM/7ohwc2jaPqnY=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]}},"1.0.1":{"name":"brace-expansion","version":"1.0.1","dependencies":{"concat-map":"0.0.0","balanced-match":"^0.2.0"},"devDependencies":{"tape":"~1.1.1"},"dist":{"shasum":"817708d72ab27a8c312d25efababaea963439ed5","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.0.1.tgz","integrity":"sha512-agencL/m7vghsxEHLqdfg0cz3hHCEo46p+VCthmo2ldRTsmW7DANziRJnYCzGPT2Rc6OaYoNmiC9Fq/6laK8Lg==","signatures":[{"sig":"MEYCIQCGL4FbAvj1GETCGq8al+snilcC+LBgaWobxTbx8NWHZAIhANmwsSB+I/6UwWGG0pJTZ61b1BqcCFCycRpzUjMB5IUG","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]}},"1.1.0":{"name":"brace-expansion","version":"1.1.0","dependencies":{"concat-map":"0.0.1","balanced-match":"^0.2.0"},"devDependencies":{"tape":"^3.0.3"},"dist":{"shasum":"c9b7d03c03f37bc704be100e522b40db8f6cfcd9","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.0.tgz","integrity":"sha512-jW1t9kL3kiXzovHnEgYNuYMnF+hHB1TlyK2wox32dPrWRvwNEJlXz3NdB5mdjFK1Pom22qVVvpGXN2hICWmvGw==","signatures":[{"sig":"MEYCIQDAPkyBXMMTJXxO2G60LgymQM/x1fVRSoTL+X3M2ijMQAIhAIy8QqTEZzxuJKSFpS2zCFxK5+XDyIaYWZeOlil5bFAa","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]}},"1.1.1":{"name":"brace-expansion","version":"1.1.1","dependencies":{"concat-map":"0.0.1","balanced-match":"^0.2.0"},"devDependencies":{"tape":"^3.0.3"},"dist":{"shasum":"da5fb78aef4c44c9e4acf525064fb3208ebab045","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.1.tgz","integrity":"sha512-8sehXzl+5+hVq+azy8bdvi/vdY1DA0eKIM+k+wK4XqBAy3e0khAcxN+CMIf6QObpDLR4LXBBH8eRRR500WDidg==","signatures":[{"sig":"MEUCIAMsztomnUx31iO0XaIv4hcdVeg9nUiL0BNflX2zT1mKAiEAnKJYmKMf1DIPlz3tsslDFKMUMZBV5K6i41Erb0rdfOE=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]}},"1.1.2":{"name":"brace-expansion","version":"1.1.2","dependencies":{"concat-map":"0.0.1","balanced-match":"^0.3.0"},"devDependencies":{"tape":"4.2.2"},"dist":{"shasum":"f21445d0488b658e2771efd870eff51df29f04ef","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.2.tgz","integrity":"sha512-QY1LGlHZzEwE7NbolI6UYCtLE2zp0I49Cx7anmMGHjwPcb5E/fN/mk5i6oERkhhx78K/UPNEwLjLhHM3tZwjcw==","signatures":[{"sig":"MEQCIGzXvMvui4rDxLgCCSSd5sHHHnPnkk+FFuMXmUmTPuasAiAI9w6HqWYhvFwjJ1Lt2kvx9juCc42nu86lNVjZVmiVBw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]}},"1.1.3":{"name":"brace-expansion","version":"1.1.3","dependencies":{"concat-map":"0.0.1","balanced-match":"^0.3.0"},"devDependencies":{"tape":"4.4.0"},"dist":{"shasum":"46bff50115d47fc9ab89854abb87d98078a10991","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.3.tgz","integrity":"sha512-JzSkuJYnfzmR0jZiCE/Nbw1I9/NL2Z2diIfhffu5Aq3nihHtfO8CNYcwxmAyTKYKWyte1b1vYBHMVhMbe+WZdw==","signatures":[{"sig":"MEYCIQDTtnEPVW6mkENQFogGyd+jwVVZk4fv5oQrv59tJZl+LQIhAIDBZRtfmnRz3bd3iBTboDlyyKBBzKcmMQRB4i13N8Aa","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]}},"1.1.4":{"name":"brace-expansion","version":"1.1.4","dependencies":{"concat-map":"0.0.1","balanced-match":"^0.4.1"},"devDependencies":{"tape":"4.5.1"},"dist":{"shasum":"464a204c77f482c085c2a36c456bbfbafb67a127","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.4.tgz","integrity":"sha512-wpJYpqGrDNnMWoi1GX8s8C4/SkHCuuLV0Sxlkvc4+rEBTNkUI2xLiUU3McR0b5dVw71Yw50l+sBGhusHNnjFnw==","signatures":[{"sig":"MEUCIQDv5gzTuC2pQtSUO2lUpdIu+EEkjv5yy57Xfhq9mKbJZAIgNucwl3w78pmRKhcaEEkqf8ALdEUhrSTClfu6fid9vy8=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]}},"1.1.5":{"name":"brace-expansion","version":"1.1.5","dependencies":{"concat-map":"0.0.1","balanced-match":"^0.4.1"},"devDependencies":{"tape":"4.5.1"},"dist":{"shasum":"f5b4ad574e2cb7ccc1eb83e6fe79b8ecadf7a526","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.5.tgz","integrity":"sha512-FtnR1B5L0wpwEeryoTeqAmxrybW2/7BI8lqG9WSk6FxHoPCg5O474xPgWWQkoS7wAilt97IWvz3hDOWtgqMNzg==","signatures":[{"sig":"MEUCIDcdxKt/UDpxuuF6QUTSAj+Ndice1oRjJYdg0ZT4vFlxAiEA/qg6+kDz31bAvPhuTGit0IkXoFtpj5xgb9i8K7XPmOM=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]}},"1.1.6":{"name":"brace-expansion","version":"1.1.6","dependencies":{"concat-map":"0.0.1","balanced-match":"^0.4.1"},"devDependencies":{"tape":"^4.6.0"},"dist":{"shasum":"7197d7eaa9b87e648390ea61fc66c84427420df9","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz","integrity":"sha512-do+EUHPJZmz1wYWxOspwBMwgEqs0T5xSClPfYRwug3giEKZoiuMN9Ans1hjT8yZZ1Dkx1oaU4yRe540HKKHA0A==","signatures":[{"sig":"MEUCIQD32m58z3rzGaG1vElCS5FolKUXPn6odedg6Xfq9KZQOAIgWSBG2qBNxWBr+2EzNkySLFXLqC2Gj9ZQkHSOkPDUabM=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]}},"1.1.7":{"name":"brace-expansion","version":"1.1.7","dependencies":{"concat-map":"0.0.1","balanced-match":"^0.4.1"},"devDependencies":{"tape":"^4.6.0","matcha":"^0.7.0"},"dist":{"shasum":"3effc3c50e000531fb720eaff80f0ae8ef23cf59","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz","integrity":"sha512-ebXXDR1wKKxJNfTM872trAU5hpKduCkTN37ipoxsh5yibWq8FfxiobiHuVlPFkspSSNhrxbPHbM4kGyDGdJ5mg==","signatures":[{"sig":"MEUCIQDjfkyICBvvj8rQb/0E8LXObvB5Ip4Son+jWmF+agQUewIgYtJplpbk9QT8k8fK4+mvwW/2SG88zw7RyfanboCbDYs=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]}},"1.1.8":{"name":"brace-expansion","version":"1.1.8","dependencies":{"concat-map":"0.0.1","balanced-match":"^1.0.0"},"devDependencies":{"tape":"^4.6.0","matcha":"^0.7.0"},"dist":{"shasum":"c07b211c7c952ec1f8efd51a77ef0d1d3990a292","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz","integrity":"sha512-Dnfc9ROAPrkkeLIUweEbh7LFT9Mc53tO/bbM044rKjhgAEyIGKvKXg97PM/kRizZIfUHaROZIoeEaWao+Unzfw==","signatures":[{"sig":"MEYCIQCnJTT7JQLt62sEnsf0tHq2Bjs0s5hzFPLTKZ0ezxe48wIhAMjCqrWYo5zNLTOR2UuSzCxYcXppfgandM0w69ZeHWpY","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]}},"1.1.9":{"name":"brace-expansion","version":"1.1.9","dependencies":{"concat-map":"0.0.1","balanced-match":"^1.0.0"},"devDependencies":{"tape":"^4.6.0","matcha":"^0.7.0"},"dist":{"shasum":"acdc7dde0e939fb3b32fe933336573e2a7dc2b7c","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.9.tgz","fileCount":3,"integrity":"sha512-/+o3o6OV1cm3WKrO7U4wykU+ZICE6HiMEuravc2d03NIuM/VaRn5iMcoQ7NyxFXjvpmRICP2EER0YOnh4yIapA==","signatures":[{"sig":"MEYCIQCAFhLoOH1TGldXfcUQuons91mJSbJrZN7qvWgErbY1lwIhALBOh4f4dcTZ4xMkCIZbI0YlooUneFTZMFuQiPvTFZVW","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9867}},"1.1.10":{"name":"brace-expansion","version":"1.1.10","dependencies":{"concat-map":"0.0.1","balanced-match":"^1.0.0"},"devDependencies":{"tape":"^4.6.0","matcha":"^0.7.0"},"dist":{"shasum":"5205cdf64c9798c180dc74b7bfc670c3974e6300","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.10.tgz","fileCount":4,"integrity":"sha512-u0KjSZq9NOEh36yRmKT/pIYOu0rpGAyUTeUmJgNd1K2tpAaUomh092TZ0fqbBGQc4hz85BVngAiB2mqekvQvIw==","signatures":[{"sig":"MEYCIQDli7mxJRbuSCfeiMcIL+s+gaQlXvfuResXwhPtt2QeKwIhAOXD8xbx/PBIDoeu5Oy4kLIhozwj20XbJgDGdsYvwrnj","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":10964}},"1.1.11":{"name":"brace-expansion","version":"1.1.11","dependencies":{"concat-map":"0.0.1","balanced-match":"^1.0.0"},"devDependencies":{"tape":"^4.6.0","matcha":"^0.7.0"},"dist":{"shasum":"3c7fcbf529d87226f3d2f52b966ff5271eb441dd","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz","fileCount":4,"integrity":"sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==","signatures":[{"sig":"MEUCIQC2I9J9tPlxp6j/HHQEZt6m3oGHr2r9mzmIpCuNqtxU8AIgEDoaUyizhrLzwPIwhskq7pIaySeBQHqkhwY/BQL5cCk=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":11059}},"2.0.0":{"name":"brace-expansion","version":"2.0.0","dependencies":{"balanced-match":"^1.0.0"},"devDependencies":{"tape":"^4.6.0","matcha":"^0.7.0"},"dist":{"shasum":"3b53b490c803c23a6a5d6c9c8b309879c37c7f98","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.0.tgz","fileCount":5,"integrity":"sha512-A4GHY1GpcTnp+Elcwp1CbKHY6ZQwwVR7QdjZk4fPetEh7oNBfICu+eLvvVvTEMHgC+SGn+XiLAgGo0MnPPBGOg==","signatures":[{"sig":"MEUCIQCr5ZL6FcHVP65o923WcJjCEbbjT/6loKJU+zYITXIhbQIgGEfe3/Y91JY20BO7ZulW1OEI8SlP/Xvlh6hngSAJcF4=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":11241,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfewZYCRA9TVsSAnZWagAAd70P/2QT8aQ9+pjZQwM2pk0Z\nB/jNeaDu5O0/Y06KZF3Pzcxl9SFVCWfEr+7WP5mqb+R+dbthggNppICoM2Tk\nmilkoIgrUecspuKsvnJ0qJRYDSktSwD1IgcY/V3Yr8jCW5J56tU5SiUozvuj\nl3od5svv9vsPilwIHnMoRS4p00La7dlKK6v6R9QgdIF300jd+F++5GmSZOmj\nRxQslhhmFcM0nxIrJ1Ku06Tino2o8E8R0XzBUZS42uexstrDk9DGTtQmjqUn\nvnR/KRlJVppSdOeQ5P0L1UjvDObub5XUdfRo4JnQDrPrDZMdItLZ8CeoEVPh\nIwBCNCBoeWxbbPgAr4QdYMTpyIidFpMDd2lhNB+UTibold67Of4tbOn5KcOG\nac1lCdmturxz0AkyxawmQDkelpLdnatWdBzwGmPDk/Nh6bCSR03iKEgT3oJI\nu+NtciBopPto2emV8eN6E9yvlpGz8b7qDxi7FgOSYvEZ4Vy7spRpj6mS8PYl\nXbkTFUaNDr1KIMHlvXjeYX1I0MfFeE5u1uWovNS+bRmPYqVo78kRxJmlEL/J\nsOGS+PEnPx2thCA9VU4IZ+uGn1dx5mR28xylmatytWU2o3kXF4clXVeosSOl\nZYBAoXlsicuQxhrLzwvkReVpfCYNYVLTRjjn1eLrrba+M+FxT8ULtj6Z5Zh+\nqlBk\r\n=GlK9\r\n-----END PGP SIGNATURE-----\r\n"}},"2.0.1":{"name":"brace-expansion","version":"2.0.1","dependencies":{"balanced-match":"^1.0.0"},"devDependencies":{"tape":"^4.6.0","@c4312/matcha":"^1.3.1"},"dist":{"shasum":"1edc459e0f0c548486ecf9fc99f2221364b9a0ae","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz","fileCount":5,"integrity":"sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==","signatures":[{"sig":"MEYCIQDgNFdV3ddgnkb39ucmGYRgdjxRfJEZcnAt+BXCAQaVPgIhAKW05a01tUGrzy0G/gZFOVqMptjiKbs9uy+dDpF0C75F","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":11486,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgM9lGCRA9TVsSAnZWagAAkYIQAIalRvvQqAOlBPALOfU+\nuIHTUBeNj/D6vRuqzPgWQVtUxRpdvXMI/aLxJx38aeZ6WgCvZWBQn3jItTEs\n3H2zWGue5+DAeWvBCqxSjdVV4ai+4EJuyS4+1D1qTm2syzT0aPdYRlhVMA/s\nOpiuPVHF1vqwSwPMCUXNW1sMi4N0qJzpAInYOCQ2NFUFZb5OssTqYQ1bzdl1\nRq/FtfkqOmz7OC/879lo3SCp+uvdXmkkQnSOGVU65HvzJp/NIvsFk5pHwo68\naRXefo/GRnqGFwFYOSqUUlBVjgEJYFdRVrYN+CNHK8iNJ6cphqz3EE1Edl1d\njT1SsFm9dJCqkfz5M/tW03vbMV88MYKhdDff5/Fugz4vcCAKfp+JcJolxUxz\nYXnB/xH/MsIEFIqwfDHYf+HFDZsZk7kJKm5JUciIV9CORiWtHz4d/y+4FYZM\n48okE1VAa5E7DVlGhTEUJUUt05JHztbm4EPklRd4/il61edoL516wp1XryxB\nSG3Jb+wLHH/ZHUQHpqrnBWvs68fxE8848EwiWIPKUk7pP/MtHdftjw2ouPSa\nD3EeHKJirZ3GAJqmwDy/vrOSB5/bQX82dGviV097AdPpnCAH6HJuaXBww+lN\nXgbxcuBiXlMuQAxpmQ578BOIGHnCo9EeauL2Ik9pHissAPUcpFCSUVZvXC3P\nJbt7\r\n=ayXm\r\n-----END PGP SIGNATURE-----\r\n"}},"3.0.0":{"name":"brace-expansion","version":"3.0.0","dependencies":{"balanced-match":"^3.0.0"},"devDependencies":{"standard":"^17.1.0","@c4312/matcha":"^1.3.1"},"dist":{"shasum":"2ba8d16a84bb3b440107587dae0fa59cf8672452","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-3.0.0.tgz","fileCount":7,"integrity":"sha512-P+6OwxY7i0tsp0Xdei2CjvVOQke51REB4c2d2wCckcMn6NBElNqLuzr6PsxFCdJ3i/cpGEkZ/Nng5I7ZkLo0CA==","signatures":[{"sig":"MEQCIEC9uzfKooJ89Q8QLlD+tzLeFwFe/78sLtWLDO3ReypKAiBnVIsCDBixEed2GXe6+kCRV/O2pdWrYiYU+YT9S1FG4A==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12214},"engines":{"node":">= 18"}},"4.0.0":{"name":"brace-expansion","version":"4.0.0","dependencies":{"balanced-match":"^3.0.0"},"devDependencies":{"standard":"^17.1.0","@c4312/matcha":"^1.3.1"},"dist":{"shasum":"bb24b89bf4d4b37d742acac89b65d1a32b379a81","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-4.0.0.tgz","fileCount":8,"integrity":"sha512-l/mOwLWs7BQIgOKrL46dIAbyCKvPV7YJPDspkuc88rHsZRlg3hptUGdU7Trv0VFP4d3xnSGBQrKu5ZvGB7UeIw==","signatures":[{"sig":"MEUCIQDrhNEy/hwZjHIlsHCYab0+IHgrz7kDfa1w6u/e+kx1EAIgOp8c3E2/Sn13tVi4fV1P31KM5fQX1SqJtVtpcVNa8gI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12770},"engines":{"node":">= 18"}},"4.0.1":{"name":"brace-expansion","version":"4.0.1","dependencies":{"balanced-match":"^3.0.0"},"devDependencies":{"standard":"^17.1.0","@c4312/matcha":"^1.3.1"},"dist":{"shasum":"3387e13eaa2992025d05ea47308f77e4a8dedd1e","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-4.0.1.tgz","fileCount":8,"integrity":"sha512-YClrbvTCXGe70pU2JiEiPLYXO9gQkyxYeKpJIQHVS/gOs6EWMQP2RYBwjFLNT322Ji8TOC3IMPfsYCedNpzKfA==","signatures":[{"sig":"MEYCIQDM35BPIuCbJPcYEBCh7CiAu49GUmmIYkH5k35GV1gmCQIhAKwPJK1YnN3VtTML0OB+JNUt9BSXLQMdK/TXeVbrLslu","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":12775},"engines":{"node":">= 18"}},"3.0.1":{"name":"brace-expansion","version":"3.0.1","dependencies":{"balanced-match":"^3.0.0"},"devDependencies":{"standard":"^17.1.0","@c4312/matcha":"^1.3.1"},"dist":{"shasum":"ca8272e391c052107d076e60da89c4b8b06bdf3c","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-3.0.1.tgz","fileCount":7,"integrity":"sha512-d+NXbXQ463UPpTMIHWzVzp8x9lG5ALx1cR+0MUo9IztykL5+U5bN07D5rlT+yQGcr1mz7ydxFaw5FdaFYW247w==","signatures":[{"sig":"MEQCIEhfp8EcrJDnKMI+oXQmK2sWQEVXPhBm/CMyG28znj4wAiB6YiEk1m4Ka4QJFvNPVxa/Qm6fd+nlNUZKH/A4a6zVjg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":12262},"engines":{"node":">= 18"}},"2.0.2":{"name":"brace-expansion","version":"2.0.2","dependencies":{"balanced-match":"^1.0.0"},"devDependencies":{"tape":"^4.6.0","@c4312/matcha":"^1.3.1"},"dist":{"shasum":"54fc53237a613d854c7bd37463aad17df87214e7","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz","fileCount":5,"integrity":"sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==","signatures":[{"sig":"MEQCIHowR6pWiAws0hC5C7DsbWOVB2Ob/pQlQIgpExp7SNSeAiBnxaRTaBM/EMpAPQicV/a54Zg9vvJzXmLkfYtCCGVOxw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":11534}},"1.1.12":{"name":"brace-expansion","version":"1.1.12","dependencies":{"concat-map":"0.0.1","balanced-match":"^1.0.0"},"devDependencies":{"tape":"^4.6.0","matcha":"^0.7.0"},"dist":{"shasum":"ab9b454466e5a8cc3a187beaad580412a9c5b843","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz","fileCount":4,"integrity":"sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==","signatures":[{"sig":"MEUCIQCefRVlAiPWPz42vj2hoqvreB3Job7AZ0kiUGVtB1yl1gIge5j1MzW2qkqi81uRNwZK1QPOMLfb8Xo8f2zlR2sYDV0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":11107}},"5.0.2":{"name":"brace-expansion","version":"5.0.2","dependencies":{"balanced-match":"^4.0.2"},"devDependencies":{"tap":"^21.5.0","tshy":"^3.0.2","mkdirp":"^3.0.1","typedoc":"^0.28.5","prettier":"^3.3.2","@types/node":"^25.2.1","@types/brace-expansion":"^1.1.2"},"dist":{"shasum":"b6c16d0791087af6c2bc463f52a8142046c06b6f","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz","fileCount":13,"integrity":"sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==","signatures":[{"sig":"MEYCIQD7+ZHkvSahE0SFk0+Culu/VO3BePPKhI2kF2OyL4173gIhAOV/hVSXit3pcggBwqV3rEmZx4Fgz+/vTfQXbvGzKA5a","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":47243},"engines":{"node":"20 || >=22"}},"5.0.3":{"name":"brace-expansion","version":"5.0.3","dependencies":{"balanced-match":"^4.0.2"},"devDependencies":{"tap":"^21.6.2","tshy":"^3.0.2","mkdirp":"^3.0.1","typedoc":"^0.28.5","prettier":"^3.3.2","@types/node":"^25.2.1","@types/brace-expansion":"^1.1.2"},"dist":{"shasum":"6a9c6c268f85b53959ec527aeafe0f7300258eef","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.3.tgz","fileCount":13,"integrity":"sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA==","signatures":[{"sig":"MEUCICEKuLObJs4oYjfzWEJorPrHqntg6aX20e/LiCk+pD1zAiEAnr6EFXsmx+rILhI5fiLKhP7cuRdwXgcyjehN9//qEI8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":47249},"engines":{"node":"18 || 20 || >=22"}},"5.0.4":{"name":"brace-expansion","version":"5.0.4","dependencies":{"balanced-match":"^4.0.2"},"devDependencies":{"tap":"^21.6.2","tshy":"^3.0.2","mkdirp":"^3.0.1","typedoc":"^0.28.5","prettier":"^3.3.2","@types/node":"^25.2.1","@types/brace-expansion":"^1.1.2"},"dist":{"shasum":"614daaecd0a688f660bbbc909a8748c3d80d4336","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz","fileCount":13,"integrity":"sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==","signatures":[{"sig":"MEUCIAPLOAnFykAviHXjnyUkdsT8T1mQr3HSoVKGdcj3WpjwAiEAsENA+JXdNMlXYoGWwv1Iq1LVztnI+/JOMBS31pf6IUI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":47248},"engines":{"node":"18 || 20 || >=22"}},"5.0.5":{"name":"brace-expansion","version":"5.0.5","dependencies":{"balanced-match":"^4.0.2"},"devDependencies":{"tap":"^21.6.2","tshy":"^3.0.2","mkdirp":"^3.0.1","typedoc":"^0.28.5","prettier":"^3.3.2","@types/node":"^25.2.1","@types/brace-expansion":"^1.1.2"},"dist":{"shasum":"dcc3a37116b79f3e1b46db994ced5d570e930fdb","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz","fileCount":13,"integrity":"sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==","signatures":[{"sig":"MEQCIAM/93qVfJEmCP8hrYAGibIXWxJsCTVN+/XMKPO3qWgTAiAuc1RNLMzatowQMrhh/nA7Q0ut3BK/xsmp1CAqUHGnZA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":47480},"engines":{"node":"18 || 20 || >=22"}},"1.1.13":{"name":"brace-expansion","version":"1.1.13","dependencies":{"concat-map":"0.0.1","balanced-match":"^1.0.0"},"devDependencies":{"tape":"^4.6.0","matcha":"^0.7.0"},"dist":{"shasum":"d37875c01dc9eff988dd49d112a57cb67b54efe6","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz","fileCount":4,"integrity":"sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==","signatures":[{"sig":"MEUCIHZgSMviF7fNVn5SAr+vNoV2YV1jQM19vvjznflJSM/mAiEA3GNP6Q+wdCy3Wy+aA6b9yFKCq0SpbLbjGT1F5ht8IwQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":11119}},"2.0.3":{"name":"brace-expansion","version":"2.0.3","dependencies":{"balanced-match":"^1.0.0"},"devDependencies":{"tape":"^4.6.0","@c4312/matcha":"^1.3.1"},"dist":{"shasum":"0493338bdd58e319b1039c67cf7ee439892c01d9","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz","fileCount":5,"integrity":"sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==","signatures":[{"sig":"MEUCIQCm9HDkYLPod42g9wGxbHNgoHKg9DB7V4WPLgJ95enF5wIgPoupo70xwfUrdqUUANKVyBgyHX9sgNLWW+L3QDAAVMo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":11546}},"3.0.2":{"name":"brace-expansion","version":"3.0.2","dependencies":{"balanced-match":"^3.0.0"},"devDependencies":{"standard":"^17.1.0","@c4312/matcha":"^1.3.1"},"dist":{"shasum":"86034d465dfdf99396918ecd3ea70a38667dfc0d","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-3.0.2.tgz","fileCount":7,"integrity":"sha512-MejuTHVkwgcG9LXTXM60Bi6GjAK2bQj6mTj5X6L5PiP4MsQWlSCImOvBe0ajK4IhFIQNVUjdrs25TQ8XkoJPug==","signatures":[{"sig":"MEUCIHZP6au3XK673I5UJzlj6bpGiibjupg+hk4zOPDXGBLGAiEAnOD52OQRG63SZWxXGB6QkKvYwO+8g5by5PrbRivbK7I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":12275},"engines":{"node":">= 18"}},"1.1.14":{"name":"brace-expansion","version":"1.1.14","dependencies":{"concat-map":"0.0.1","balanced-match":"^1.0.0"},"devDependencies":{"tape":"^4.6.0","matcha":"^0.7.0"},"dist":{"shasum":"d9de602370d91347cd9ddad1224d4fd701eb348b","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz","fileCount":4,"integrity":"sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==","signatures":[{"sig":"MEUCIAUfWjoiHEMuZvGFZGPbXWyKZjkk+UD5Zps2d54+ssP7AiEAj3kldXMcqMQXCkUq6zFMeBk7UQyIsv+VgWEGZ4UFvIc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":11282}},"2.1.0":{"name":"brace-expansion","version":"2.1.0","dependencies":{"balanced-match":"^1.0.0"},"devDependencies":{"tape":"^4.6.0","@c4312/matcha":"^1.3.1"},"dist":{"shasum":"4f41a41190216ee36067ec381526fe9539c4f0ae","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz","fileCount":5,"integrity":"sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==","signatures":[{"sig":"MEYCIQCyyN529JnurgAIPSj+St1nn0+Q+wbtVS40/nAttdbHiQIhAKxDhLKB4jRjJt13OIFmMoSa8ZsF5y9v2r+1MYePOtrk","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":11715}},"5.0.6":{"name":"brace-expansion","version":"5.0.6","dependencies":{"balanced-match":"^4.0.2"},"devDependencies":{"tap":"^21.6.2","tshy":"^3.0.2","mkdirp":"^3.0.1","typedoc":"^0.28.5","prettier":"^3.3.2","@types/node":"^25.2.1","@types/brace-expansion":"^1.1.2"},"dist":{"shasum":"ec68fe0a641a29d8711579caf641d05bae1f2285","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz","fileCount":13,"integrity":"sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==","signatures":[{"sig":"MEUCIEc0B0ZPaCqXoIxUTVDL68BoVYjRY9BFqqqUPKQWC5avAiEA3lMlo9Jel0GVEUVgM0hqexEZcz4JHDIXRvUHTKqTDPQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":47612},"engines":{"node":"18 || 20 || >=22"}},"2.1.1":{"name":"brace-expansion","version":"2.1.1","dependencies":{"balanced-match":"^1.0.0"},"devDependencies":{"tape":"^4.6.0","@c4312/matcha":"^1.3.1"},"dist":{"shasum":"c68b1c4111c76aae3a6fba55d496cee10c39dad8","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz","fileCount":5,"integrity":"sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==","signatures":[{"sig":"MEUCIQC+w3SoF8ln58Z1n8EUM1eV1iMGdEnGl65fr/avK1mehQIgAKo6IUsxz153V2I96kkf2F/LTne60S8jjobisjp+PHI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":11733}},"1.1.15":{"name":"brace-expansion","version":"1.1.15","dependencies":{"balanced-match":"^1.0.0","concat-map":"0.0.1"},"devDependencies":{"matcha":"^0.7.0","tape":"^4.6.0"},"dist":{"integrity":"sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==","shasum":"a6d90d54067236e5f42570a3b7378d594d9b7738","tarball":"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz","fileCount":4,"unpackedSize":11300,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDk8wK1DcOONVJ7Qtyy2pJgv+hCtg2hgWdiCvvmXFHDzQIgRnCW07bbBJcF4/HAB4Mux1ps3R94iXF6uDXegW1w/QU="}]}}},"modified":"2026-05-26T08:43:09.075Z"} \ No newline at end of file diff --git a/frontend/.npm-cache/_cacache/content-v2/sha512/04/b2/374e5d535b73ef97bd25df2ab763ae22f9ac29c17aac181616924a8cb676d782b303fb28fbae15b492e103c7325a6171a3116e6881aa4a34c10a34c8e26c b/frontend/.npm-cache/_cacache/content-v2/sha512/04/b2/374e5d535b73ef97bd25df2ab763ae22f9ac29c17aac181616924a8cb676d782b303fb28fbae15b492e103c7325a6171a3116e6881aa4a34c10a34c8e26c new file mode 100644 index 0000000..865d6b6 Binary files /dev/null and b/frontend/.npm-cache/_cacache/content-v2/sha512/04/b2/374e5d535b73ef97bd25df2ab763ae22f9ac29c17aac181616924a8cb676d782b303fb28fbae15b492e103c7325a6171a3116e6881aa4a34c10a34c8e26c differ diff --git a/frontend/.npm-cache/_cacache/content-v2/sha512/04/ba/e011c453c17da8ea01b118e08dc8cbc64a9df96287ee633c3d87520c4d198aaadb40659554ebb6dd6fd3ebdaf50703cfa3de2dad25f8cee82ebee26c864c b/frontend/.npm-cache/_cacache/content-v2/sha512/04/ba/e011c453c17da8ea01b118e08dc8cbc64a9df96287ee633c3d87520c4d198aaadb40659554ebb6dd6fd3ebdaf50703cfa3de2dad25f8cee82ebee26c864c new file mode 100644 index 0000000..fc33d53 Binary files /dev/null and b/frontend/.npm-cache/_cacache/content-v2/sha512/04/ba/e011c453c17da8ea01b118e08dc8cbc64a9df96287ee633c3d87520c4d198aaadb40659554ebb6dd6fd3ebdaf50703cfa3de2dad25f8cee82ebee26c864c differ diff --git a/frontend/.npm-cache/_cacache/content-v2/sha512/04/c8/4b0ff4b0f866c90b6d42fd48326995f8d673edf1b51383e8d6c837a0edeed8378c4e334e583d221771e0029d756dab2130fcb30295440cb4c67e3c61a9a9 b/frontend/.npm-cache/_cacache/content-v2/sha512/04/c8/4b0ff4b0f866c90b6d42fd48326995f8d673edf1b51383e8d6c837a0edeed8378c4e334e583d221771e0029d756dab2130fcb30295440cb4c67e3c61a9a9 new file mode 100644 index 0000000..73d46d4 Binary files /dev/null and b/frontend/.npm-cache/_cacache/content-v2/sha512/04/c8/4b0ff4b0f866c90b6d42fd48326995f8d673edf1b51383e8d6c837a0edeed8378c4e334e583d221771e0029d756dab2130fcb30295440cb4c67e3c61a9a9 differ diff --git a/frontend/.npm-cache/_cacache/content-v2/sha512/04/dd/b607979a30c23d50cb63ac677983978260fa423c3532d052576d8b1a4f9cd8c6314e7244b9dd2403137a56915a16a475d56f706b61c10de13c1ae7907970 b/frontend/.npm-cache/_cacache/content-v2/sha512/04/dd/b607979a30c23d50cb63ac677983978260fa423c3532d052576d8b1a4f9cd8c6314e7244b9dd2403137a56915a16a475d56f706b61c10de13c1ae7907970 new file mode 100644 index 0000000..2c52fd7 Binary files /dev/null and b/frontend/.npm-cache/_cacache/content-v2/sha512/04/dd/b607979a30c23d50cb63ac677983978260fa423c3532d052576d8b1a4f9cd8c6314e7244b9dd2403137a56915a16a475d56f706b61c10de13c1ae7907970 differ diff --git a/frontend/.npm-cache/_cacache/content-v2/sha512/04/ec/e21487c4fbaa2c1cef45a091b8ce3a0751cbc8edf4cd052a5d030acd1f4fd32efce3b24da8a3c5d248e4f61e1a94ca164f7c7bf850e7dfa09f6810443b02 b/frontend/.npm-cache/_cacache/content-v2/sha512/04/ec/e21487c4fbaa2c1cef45a091b8ce3a0751cbc8edf4cd052a5d030acd1f4fd32efce3b24da8a3c5d248e4f61e1a94ca164f7c7bf850e7dfa09f6810443b02 new file mode 100644 index 0000000..ba18e46 Binary files /dev/null and b/frontend/.npm-cache/_cacache/content-v2/sha512/04/ec/e21487c4fbaa2c1cef45a091b8ce3a0751cbc8edf4cd052a5d030acd1f4fd32efce3b24da8a3c5d248e4f61e1a94ca164f7c7bf850e7dfa09f6810443b02 differ diff --git a/frontend/.npm-cache/_cacache/content-v2/sha512/05/1e/d5bc30951cefaadb10445ac9314ba0c9135a919dbec3c7352ba206fbd425a849f89c07162c88019df8a9749a6abf329ac6f7202b464cab4314cee978cccc b/frontend/.npm-cache/_cacache/content-v2/sha512/05/1e/d5bc30951cefaadb10445ac9314ba0c9135a919dbec3c7352ba206fbd425a849f89c07162c88019df8a9749a6abf329ac6f7202b464cab4314cee978cccc new file mode 100644 index 0000000..0f24e8a Binary files /dev/null and b/frontend/.npm-cache/_cacache/content-v2/sha512/05/1e/d5bc30951cefaadb10445ac9314ba0c9135a919dbec3c7352ba206fbd425a849f89c07162c88019df8a9749a6abf329ac6f7202b464cab4314cee978cccc differ diff --git a/frontend/.npm-cache/_cacache/content-v2/sha512/05/d6/e8cbe97bb40dce196e858f21475a43f92ee0728f54e4df72e3caad1ac72cdd93dfff2528b6bb77cfd504a677528dc2ae9538a606940bbcec28ac562afa3f b/frontend/.npm-cache/_cacache/content-v2/sha512/05/d6/e8cbe97bb40dce196e858f21475a43f92ee0728f54e4df72e3caad1ac72cdd93dfff2528b6bb77cfd504a677528dc2ae9538a606940bbcec28ac562afa3f new file mode 100644 index 0000000..25ccaf2 Binary files /dev/null and b/frontend/.npm-cache/_cacache/content-v2/sha512/05/d6/e8cbe97bb40dce196e858f21475a43f92ee0728f54e4df72e3caad1ac72cdd93dfff2528b6bb77cfd504a677528dc2ae9538a606940bbcec28ac562afa3f differ diff --git a/frontend/.npm-cache/_cacache/content-v2/sha512/05/ff/882e6060adeb54add271cd73344a05cb6775df89a52e3a3fc82901ee4d78a9fb4e579febb21187558349180e2a5305c2eb095c94cc03f3ed0980adbd269b b/frontend/.npm-cache/_cacache/content-v2/sha512/05/ff/882e6060adeb54add271cd73344a05cb6775df89a52e3a3fc82901ee4d78a9fb4e579febb21187558349180e2a5305c2eb095c94cc03f3ed0980adbd269b new file mode 100644 index 0000000..5041a62 Binary files /dev/null and b/frontend/.npm-cache/_cacache/content-v2/sha512/05/ff/882e6060adeb54add271cd73344a05cb6775df89a52e3a3fc82901ee4d78a9fb4e579febb21187558349180e2a5305c2eb095c94cc03f3ed0980adbd269b differ diff --git a/frontend/.npm-cache/_cacache/content-v2/sha512/06/d8/f604e38ef37a375b21f9f5ef0c817b3111055c6ab9143a9118aee6c1d2eaf09cdd74c90dfae2bb22072535d67665a966199b4e62fe87fb8a8e26ce2841b5 b/frontend/.npm-cache/_cacache/content-v2/sha512/06/d8/f604e38ef37a375b21f9f5ef0c817b3111055c6ab9143a9118aee6c1d2eaf09cdd74c90dfae2bb22072535d67665a966199b4e62fe87fb8a8e26ce2841b5 new file mode 100644 index 0000000..7e9663e Binary files /dev/null and b/frontend/.npm-cache/_cacache/content-v2/sha512/06/d8/f604e38ef37a375b21f9f5ef0c817b3111055c6ab9143a9118aee6c1d2eaf09cdd74c90dfae2bb22072535d67665a966199b4e62fe87fb8a8e26ce2841b5 differ diff --git a/frontend/.npm-cache/_cacache/content-v2/sha512/08/63/9f389a968e0daa5bf31beb336c0e6faee6f150f03c577db334f73ebda7967afa61358a43f68d45f0fa3e363dfd574d8103d919e2e5ff799e961ebb030340 b/frontend/.npm-cache/_cacache/content-v2/sha512/08/63/9f389a968e0daa5bf31beb336c0e6faee6f150f03c577db334f73ebda7967afa61358a43f68d45f0fa3e363dfd574d8103d919e2e5ff799e961ebb030340 new file mode 100644 index 0000000..bd9d4e7 Binary files /dev/null and b/frontend/.npm-cache/_cacache/content-v2/sha512/08/63/9f389a968e0daa5bf31beb336c0e6faee6f150f03c577db334f73ebda7967afa61358a43f68d45f0fa3e363dfd574d8103d919e2e5ff799e961ebb030340 differ diff --git a/frontend/.npm-cache/_cacache/content-v2/sha512/09/5f/535b76377fcff04f405115cd7f280550dd350789799a01be955bdbed88c15fed22e831dd4f7407385b728538511304951bf7429ab47aa5b1931657e47d1a b/frontend/.npm-cache/_cacache/content-v2/sha512/09/5f/535b76377fcff04f405115cd7f280550dd350789799a01be955bdbed88c15fed22e831dd4f7407385b728538511304951bf7429ab47aa5b1931657e47d1a new file mode 100644 index 0000000..bcfa1cf Binary files /dev/null and b/frontend/.npm-cache/_cacache/content-v2/sha512/09/5f/535b76377fcff04f405115cd7f280550dd350789799a01be955bdbed88c15fed22e831dd4f7407385b728538511304951bf7429ab47aa5b1931657e47d1a differ diff --git a/frontend/.npm-cache/_cacache/content-v2/sha512/09/e8/7eee8c79a9eecb26e2c7a18d1f7a1de91ee5031c071151ec8bd95620859c1fa64348cbffbc39c8346b752e4a86336af9b2970b8b59039fde19748e330c23 b/frontend/.npm-cache/_cacache/content-v2/sha512/09/e8/7eee8c79a9eecb26e2c7a18d1f7a1de91ee5031c071151ec8bd95620859c1fa64348cbffbc39c8346b752e4a86336af9b2970b8b59039fde19748e330c23 new file mode 100644 index 0000000..f09abb3 Binary files /dev/null and b/frontend/.npm-cache/_cacache/content-v2/sha512/09/e8/7eee8c79a9eecb26e2c7a18d1f7a1de91ee5031c071151ec8bd95620859c1fa64348cbffbc39c8346b752e4a86336af9b2970b8b59039fde19748e330c23 differ diff --git a/frontend/.npm-cache/_cacache/content-v2/sha512/0b/1c/29b7649f4f34ed5dc7ce97318479ef0ef9cf8c994806acd8817179ee5b1b852477ba6b91f3eeac21c1ee4e81a498234209be42ea597d40486f9c24e90488 b/frontend/.npm-cache/_cacache/content-v2/sha512/0b/1c/29b7649f4f34ed5dc7ce97318479ef0ef9cf8c994806acd8817179ee5b1b852477ba6b91f3eeac21c1ee4e81a498234209be42ea597d40486f9c24e90488 new file mode 100644 index 0000000..356647d Binary files /dev/null and b/frontend/.npm-cache/_cacache/content-v2/sha512/0b/1c/29b7649f4f34ed5dc7ce97318479ef0ef9cf8c994806acd8817179ee5b1b852477ba6b91f3eeac21c1ee4e81a498234209be42ea597d40486f9c24e90488 differ diff --git a/frontend/.npm-cache/_cacache/content-v2/sha512/0c/25/eee887e1a9c92ced364a6371f1a77cbaaa9858e522599ab58c0eb29c11148e5d641d32153d220fcf62bcf2c3fba5f63388ca1d0de0cd2d6c2e61a1d83c77 b/frontend/.npm-cache/_cacache/content-v2/sha512/0c/25/eee887e1a9c92ced364a6371f1a77cbaaa9858e522599ab58c0eb29c11148e5d641d32153d220fcf62bcf2c3fba5f63388ca1d0de0cd2d6c2e61a1d83c77 new file mode 100644 index 0000000..fa3d42e Binary files /dev/null and b/frontend/.npm-cache/_cacache/content-v2/sha512/0c/25/eee887e1a9c92ced364a6371f1a77cbaaa9858e522599ab58c0eb29c11148e5d641d32153d220fcf62bcf2c3fba5f63388ca1d0de0cd2d6c2e61a1d83c77 differ diff --git a/frontend/.npm-cache/_cacache/content-v2/sha512/0d/cc/f2ddbacf27762d8134d9f833b56e1ddc42ae30f80b4df2868d13472f5ca8a5ef1ecd51e52e954056b2b65c72bf3df42552bae03bade0601d37d8a4882389 b/frontend/.npm-cache/_cacache/content-v2/sha512/0d/cc/f2ddbacf27762d8134d9f833b56e1ddc42ae30f80b4df2868d13472f5ca8a5ef1ecd51e52e954056b2b65c72bf3df42552bae03bade0601d37d8a4882389 new file mode 100644 index 0000000..9675654 --- /dev/null +++ b/frontend/.npm-cache/_cacache/content-v2/sha512/0d/cc/f2ddbacf27762d8134d9f833b56e1ddc42ae30f80b4df2868d13472f5ca8a5ef1ecd51e52e954056b2b65c72bf3df42552bae03bade0601d37d8a4882389 @@ -0,0 +1 @@ +{"source":1120812,"name":"dompurify","dependency":"dompurify","title":"DOMPurify: SAFE_FOR_TEMPLATES bypass - template expressions survive sanitization inside