feat: add compliant data connectors and lineage

- add authorized nine-source crawler connectors with security controls and packaged schemas
- add the school internship contract to the vendor data standard center
- add bidirectional campus data-to-report lineage with gap ownership and remediation

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
This commit is contained in:
lofyer
2026-08-24 16:28:01 +08:00
co-authored by factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
parent 92515928d9
commit 8dff9847e3
46 changed files with 6145 additions and 55 deletions
@@ -62,6 +62,16 @@ parse(snapshot) 解析为来源 Schema
health() 返回入口可达性、延迟和错误分类
```
参考实现位于 [`../crawler/`](../crawler/),逐来源接入方式和授权门禁见 [`../../docs/crawler-source-implementation.md`](../../docs/crawler-source-implementation.md)。连接器运行时必须遵守以下硬约束:
- 所有外部来源默认禁用,只有来源审批状态为 `approved` 才允许公网运行;
- 商业平台仅接入官方合作 API 或授权数据包,不实现登录自动化、验证码处理、私有接口逆向和反自动化规避;
- 公开页面任务同时执行书面授权、robots.txt、域名 allowlist、公共地址解析和来源级限速检查;
- 重定向后的每个 URL 重新执行相同安全校验,禁止访问回环、内网、链路本地和云元数据地址;
- User-Agent 必须标识本系统并提供真实技术联系邮箱,不伪装普通浏览器;
- Authorization、Cookie 和签名密钥只从 Vault/KMS 引用注入,不写入任务、Raw、日志或异常;
- 登录页、验证码、安全验证、访问封禁和结构变化均触发停止或隔离,不尝试绕过。
连接器发布物必须包含:
- 代码仓库、语义版本、提交摘要和构建镜像摘要;
@@ -221,6 +231,7 @@ ISSUE / WORK_ORDER
## 9. 安全与运维
- 源端凭据使用 Vault/KMS 管理,配置和日志只保存密钥引用;
- 来源授权、条款与 robots 快照作为连接器发布证据;授权到期自动停止调度;
- 采集节点使用独立网络出口策略与最小权限;
- 控制台操作采用 RBAC,并区分运营、开发、发布审批和审计;
- 原始对象启用版本、对象锁和生命周期;
+16 -11
View File
@@ -23,19 +23,21 @@ python3 -m http.server 8080
5. 执行质量校验、企业归一、岗位分类和技能抽取;
6. 通过带 Manifest、Schema、质量报告、血缘和校验和的数据包向学校交付。
## 已纳入的正式数据源
## 已纳入的目标数据源
| 类别 | 数据源 | 原型状态 | 目标数据 |
| 类别 | 数据源 | 生产接入方式 | 目标数据 |
|---|---|---|---|
| 商业平台 | BOSS直聘 | 正式运行 | 岗位、企业、地区、薪资、岗位职责、技能 |
| 商业平台 | 智联招聘 | 正式运行 | 岗位、企业、地区、薪资、岗位职责、技能 |
| 公共平台 | 全国中小企业招聘平台 | 正式运行 | 中小企业岗位、校招、实习和招聘活动 |
| 公共平台 | 国家大学生就业服务平台 | 正式运行 | 高校毕业生岗位、专场招聘和实习 |
| 公共平台 | 中国公共招聘网 | 正式运行 | 公共就业岗位、重点行业和招聘活动 |
| 公共平台 | 国聘 | 正式运行 | 国资央企岗位和校园招聘 |
| 公共平台 | 杭州人才网 | 降速保护 | 杭州都市圈企业和岗位 |
| 校内系统 | 就业管理系统 | 正式运行 | 毕业去向、岗位、企业、薪资和专业相关度 |
| 校内系统 | 实习管理系统 | 正式运行 | 实习岗位、企业、工资、过程和企业评价 |
| 商业平台 | BOSS直聘 | 官方合作 API / 授权数据包 | 岗位、企业、地区、薪资、岗位职责、技能 |
| 商业平台 | 智联招聘 | 官方合作 API / 书面授权数据包 | 岗位、企业、地区、薪资、岗位职责、技能 |
| 公共平台 | 全国中小企业招聘平台 | 官方接口优先;获准公开页 | 中小企业岗位、校招、实习和招聘活动 |
| 公共平台 | 国家大学生就业服务平台 | 官方接口优先;获准公开页 | 高校毕业生岗位、专场招聘和实习 |
| 公共平台 | 中国公共招聘网 | 官方交换 / 提供单位授权 | 公共就业岗位、重点行业和招聘活动 |
| 公共平台 | 国聘 | 官方合作 API / 授权数据包 | 国资央企岗位和校园招聘 |
| 公共平台 | 杭州人才网 | 书面许可接口 / 低速公开页 | 杭州都市圈企业和岗位 |
| 校内系统 | 就业管理系统 | 租户只读视图 / API / 文件 | 毕业去向、岗位、企业、薪资和专业相关度 |
| 校内系统 | 实习管理系统 | 租户 API / 文件 | 实习岗位、企业、工资、过程和企业评价 |
页面上的“正式运行”、记录数、成功率和时间线均为静态产品样板数据,不代表仓库当前正在访问这些站点。生产连接器默认禁止公网访问,必须完成来源授权、robots、域名白名单、限速和小样本结构审批后才能启用。逐来源方案见 [`../../docs/crawler-source-implementation.md`](../../docs/crawler-source-implementation.md),实现位于 [`../crawler/`](../crawler/)。
## 交互范围
@@ -90,6 +92,9 @@ python3 -m http.server 8080
- `schemas/school-employment.schema.json`
- `SCHOOL-EMPLOYMENT V2.2`
- 校内就业事实契约,包含租户隔离和学生令牌化要求
- `schemas/school-internship.schema.json`
- `SCHOOL-INTERNSHIP V2.1`
- 校内实习事实契约,包含租户隔离、学生令牌化、岗位任务和评价证据
- `schemas/package-manifest.schema.json`
- `PACKAGE-MANIFEST V1.2`
- 版本化导入、导出和学校交付包清单
+36
View File
@@ -804,6 +804,42 @@ const contracts = {
["质量阈值", "专业代码合法率100%,必填完整率≥95%,学生专业关联率≥98%。"],
],
},
"school-internship": {
key: "SCHOOL-INTERNSHIP",
title: "校内实习事实数据标准",
version: "V2.1.0",
description: "统一学生实习岗位、企业、起止日期、状态、工资、岗位任务和评价事实,支持租户隔离和敏感身份最小化。",
schemaPath: "./schemas/school-internship.schema.json",
fields: 30,
required: 14,
owner: "平台数据标准委员会",
status: "生产已发布",
release: "2026-08-24",
compatibility: "兼容 V2.0,补充任务与评价证据",
fieldsPreview: [
["tenant_id", "string", "是", "学校租户标识", "平台分配"],
["internship_id", "string", "是", "实习业务编号", "租户内唯一"],
["student_token", "string", "是", "学生不可逆令牌", "禁止明文学号"],
["program_code", "string", "是", "专业代码", "教育部专业目录"],
["enterprise_token", "string", "否", "企业统一标识", "令牌化"],
["job_title", "string", "是", "实习岗位名称", "业务原文"],
["job_tasks", "array<string>", "否", "实习岗位任务", "学校确认"],
["start_date", "date", "是", "开始日期", "YYYY-MM-DD"],
["end_date", "date", "否", "结束日期", "YYYY-MM-DD"],
["status", "string", "是", "实习状态", "受控枚举"],
["salary_monthly", "number", "否", "税前月实习工资", "元/月"],
["evidence_reference", "string", "否", "校内证据引用", "不传附件"],
["source_updated_at", "datetime", "否", "业务更新时间", "增量水位"],
["content_hash", "string", "是", "业务内容哈希", "SHA-256"],
],
rules: [
["租户隔离", "任务、认证、水位、Raw、隔离区和输出目录均按 tenant_id 隔离。"],
["身份最小化", "平台只接收 student_token,拒绝姓名、身份证、手机号、邮箱和明文学号。"],
["企业要求", "进行中或已完成实习必须提供企业令牌或企业名称。"],
["证据引用", "敏感附件保留在学校系统,平台只保存 evidence_reference。"],
["增量幂等", "tenant_id + source_record_id + source_updated_at 形成增量与幂等边界。"],
],
},
"package-manifest": {
key: "PACKAGE-MANIFEST",
title: "数据交付包清单标准",
+2 -1
View File
@@ -395,6 +395,7 @@
<div class="contract-tabs" id="contractTabs">
<button class="active" data-contract="external-job"><span>JOB-SIGNAL</span><strong>外部岗位信号</strong><small>V3.0 · 39字段</small></button>
<button data-contract="school-employment"><span>SCHOOL-EMPLOYMENT</span><strong>校内就业事实</strong><small>V2.2 · 32字段</small></button>
<button data-contract="school-internship"><span>SCHOOL-INTERNSHIP</span><strong>校内实习事实</strong><small>V2.1 · 30字段</small></button>
<button data-contract="package-manifest"><span>PACKAGE-MANIFEST</span><strong>交付包清单</strong><small>V1.2 · 21字段</small></button>
</div>
<div id="contractContent"></div>
@@ -425,7 +426,7 @@
<small>最大 2GB;大文件将自动分片并计算 SHA-256</small>
</label>
<div class="import-configuration">
<label><span>目标契约</span><select id="importContract"><option value="external-job">JOB-SIGNAL V3.0</option><option value="school-employment">SCHOOL-EMPLOYMENT V2.2</option></select></label>
<label><span>目标契约</span><select id="importContract"><option value="external-job">JOB-SIGNAL V3.0</option><option value="school-employment">SCHOOL-EMPLOYMENT V2.2</option><option value="school-internship">SCHOOL-INTERNSHIP V2.1</option></select></label>
<label><span>导入模式</span><select id="importMode"><option>新增或更新 UPSERT</option><option>初次全量 FULL</option><option>仅质量验证 DRY-RUN</option></select></label>
</div>
<div class="import-preview" id="importPreview">
Binary file not shown.

Before

Width:  |  Height:  |  Size: 414 KiB

After

Width:  |  Height:  |  Size: 360 KiB

+1
View File
@@ -17,4 +17,5 @@
|---|---|---|
| `JOB-SIGNAL` | 3.0.0 | 商业招聘平台、公共就业平台、活动聚合平台 |
| `SCHOOL-EMPLOYMENT` | 2.2.0 | 学校就业管理系统、数据库视图、API和标准文件 |
| `SCHOOL-INTERNSHIP` | 2.1.0 | 学校实习管理系统、API和标准文件 |
| `PACKAGE-MANIFEST` | 1.2.0 | 导入、导出、租户交付和归档;新增可选发布候选编号与状态 |
@@ -0,0 +1,222 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schemas.edu-industry.cn/school-internship/2.1.0/schema.json",
"title": "SCHOOL-INTERNSHIP V2.1 校内实习事实",
"description": "职业院校学生实习事实统一契约,采用租户隔离、身份最小化和证据引用设计。",
"type": "object",
"additionalProperties": false,
"required": [
"tenant_id",
"record_id",
"internship_id",
"student_token",
"program_code",
"job_title",
"start_date",
"status",
"source_system",
"source_record_id",
"created_at",
"updated_at",
"data_version",
"content_hash"
],
"properties": {
"tenant_id": {
"type": "string",
"pattern": "^TENANT-[A-Z0-9-]{4,64}$",
"description": "学校租户标识,所有存储、任务和查询必须同时校验。"
},
"record_id": {
"type": "string",
"format": "uuid",
"description": "平台全局唯一记录标识。"
},
"internship_id": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"description": "学校租户内的实习业务编号。"
},
"student_token": {
"type": "string",
"pattern": "^STU_[A-Za-z0-9_-]{32,128}$",
"description": "学校侧生成的学生不可逆令牌,禁止传输姓名、身份证和明文学号。"
},
"cohort": {
"type": ["integer", "null"],
"minimum": 2000,
"maximum": 2100,
"description": "学生届次。"
},
"college_code": {
"type": ["string", "null"],
"maxLength": 64,
"description": "学校内部学院代码。"
},
"program_code": {
"type": "string",
"pattern": "^[0-9A-Z]{4,12}$",
"description": "教育部职业教育专业目录代码。"
},
"enterprise_token": {
"type": ["string", "null"],
"pattern": "^ENT_[A-Za-z0-9_-]{24,128}$",
"description": "学校侧或平台企业主数据生成的企业令牌。"
},
"enterprise_name": {
"type": ["string", "null"],
"maxLength": 300,
"description": "用于业务核验的企业名称;导出时按数据范围策略处理。"
},
"enterprise_industry_code": {
"type": ["string", "null"],
"maxLength": 32,
"description": "企业行业代码。"
},
"region_code": {
"type": ["string", "null"],
"pattern": "^[0-9]{6}$",
"description": "实习地区 GB/T 2260 六位代码。"
},
"workplace": {
"type": ["string", "null"],
"maxLength": 500,
"description": "实习地点业务文本。"
},
"job_title": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "实习岗位名称。"
},
"job_code": {
"type": ["string", "null"],
"maxLength": 32,
"description": "映射到统一岗位词典后的岗位代码。"
},
"job_tasks": {
"type": "array",
"maxItems": 100,
"uniqueItems": true,
"items": {
"type": "string",
"maxLength": 500
},
"description": "经学校确认的实习岗位任务。"
},
"start_date": {
"type": "string",
"format": "date",
"description": "实习开始日期。"
},
"end_date": {
"type": ["string", "null"],
"format": "date",
"description": "计划或实际结束日期。"
},
"status": {
"type": "string",
"enum": ["planned", "active", "completed", "terminated", "cancelled"],
"description": "实习业务状态。"
},
"salary_monthly": {
"type": ["number", "null"],
"minimum": 0,
"maximum": 10000000,
"description": "确认后的税前月实习工资,单位元。"
},
"enterprise_mentor_evaluation": {
"type": ["string", "null"],
"maxLength": 4000,
"description": "企业导师业务评价,禁止包含学生敏感身份信息。"
},
"school_evaluation": {
"type": ["string", "null"],
"maxLength": 4000,
"description": "学校指导教师或管理部门评价。"
},
"evidence_reference": {
"type": ["string", "null"],
"maxLength": 256,
"description": "学校系统内的证据引用编号,不传输敏感附件。"
},
"source_system": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"description": "学校来源系统代码。"
},
"source_record_id": {
"type": "string",
"minLength": 1,
"maxLength": 256,
"description": "校内来源系统记录标识。"
},
"source_updated_at": {
"type": ["string", "null"],
"format": "date-time",
"description": "校内来源系统业务更新时间,建议作为增量水位。"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "平台记录创建时间。"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "平台记录更新时间。"
},
"data_version": {
"type": "string",
"pattern": "^SCH-INT-[0-9]{8}(?:-[0-9]{2})?$",
"description": "校内实习数据版本。"
},
"is_deleted": {
"type": "boolean",
"default": false,
"description": "版本化软删除标识。"
},
"content_hash": {
"type": "string",
"pattern": "^[a-f0-9]{64}$",
"description": "去除非业务差异后的记录内容 SHA-256。"
}
},
"allOf": [
{
"if": {
"properties": {
"status": {
"enum": ["active", "completed"]
}
},
"required": ["status"]
},
"then": {
"anyOf": [
{
"properties": {
"enterprise_token": {
"type": "string",
"pattern": "^ENT_[A-Za-z0-9_-]{24,128}$"
}
},
"required": ["enterprise_token"]
},
{
"properties": {
"enterprise_name": {
"type": "string",
"minLength": 1,
"maxLength": 300
}
},
"required": ["enterprise_name"]
}
]
}
}
]
}
+1 -1
View File
@@ -1923,7 +1923,7 @@ textarea:focus {
.contract-tabs {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 10px;
margin-bottom: 13px;
}