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
+924
View File
@@ -3085,6 +3085,840 @@ svg {
font-weight: 600;
}
.data-lineage-panel {
margin-bottom: 14px;
overflow: hidden;
background:
radial-gradient(circle at 98% 1%, rgba(198, 230, 111, 0.08), transparent 21%),
white;
}
.data-lineage-header {
align-items: flex-start;
}
.data-lineage-header h2 {
margin-bottom: 7px;
}
.data-lineage-header p {
max-width: 720px;
margin: 0;
color: var(--muted);
line-height: 1.65;
}
.lineage-snapshot-badge {
display: inline-flex;
flex: 0 0 auto;
align-items: center;
gap: 7px;
padding: 8px 11px;
color: var(--green);
background: var(--green-soft);
border: 1px solid #d2e8db;
border-radius: 9px;
font-weight: 700;
}
.lineage-snapshot-badge i {
width: 7px;
height: 7px;
background: var(--green);
border-radius: 50%;
box-shadow: 0 0 0 4px rgba(35, 135, 101, 0.11);
}
.data-lineage-toolbar {
display: grid;
grid-template-columns: auto minmax(280px, 1fr) auto;
align-items: end;
gap: 12px;
margin-top: 18px;
padding: 12px;
background: #f4f7f4;
border: 1px solid #e5ebe6;
border-radius: 12px;
}
.lineage-mode-switch {
display: flex;
gap: 4px;
padding: 4px;
background: #e8ede9;
border-radius: 9px;
}
.lineage-mode-switch button {
min-height: 38px;
padding: 0 13px;
color: var(--muted);
background: transparent;
border-radius: 7px;
font-weight: 700;
white-space: nowrap;
}
.lineage-mode-switch button.active {
color: white;
background: var(--green);
box-shadow: 0 4px 12px rgba(23, 107, 79, 0.18);
}
.lineage-selector {
display: grid;
min-width: 0;
gap: 5px;
color: var(--muted);
font-weight: 600;
}
.lineage-selector select {
width: 100%;
min-height: 38px;
padding: 0 34px 0 11px;
overflow: hidden;
color: var(--ink);
background: white;
border: 1px solid #dfe6e1;
border-radius: 8px;
text-overflow: ellipsis;
}
.lineage-gap-toggle {
display: flex;
min-height: 38px;
align-items: center;
cursor: pointer;
}
.lineage-gap-toggle input {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
opacity: 0;
}
.lineage-gap-toggle > span {
display: inline-flex;
align-items: center;
gap: 8px;
color: var(--muted);
font-weight: 700;
white-space: nowrap;
}
.lineage-gap-toggle > span i {
position: relative;
width: 38px;
height: 22px;
background: #cbd4ce;
border-radius: 12px;
transition: background 0.18s ease;
}
.lineage-gap-toggle > span i::after {
position: absolute;
top: 3px;
left: 3px;
width: 16px;
height: 16px;
background: white;
border-radius: 50%;
box-shadow: 0 2px 5px rgba(21, 54, 42, 0.2);
content: "";
transition: transform 0.18s ease;
}
.lineage-gap-toggle input:checked + span {
color: #9a6515;
}
.lineage-gap-toggle input:checked + span i {
background: var(--amber);
}
.lineage-gap-toggle input:checked + span i::after {
transform: translateX(16px);
}
.lineage-gap-toggle input:focus-visible + span i {
outline: 3px solid rgba(35, 135, 101, 0.2);
outline-offset: 2px;
}
.lineage-summary-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 9px;
margin-top: 12px;
}
.lineage-summary-grid article {
min-width: 0;
padding: 13px 14px;
background: #fafbf9;
border: 1px solid var(--line-soft);
border-radius: 10px;
}
.lineage-summary-grid article.warning {
background: #fff9ed;
border-color: #efdcae;
}
.lineage-summary-grid article.ready {
background: #f1f8f4;
border-color: #d8e9de;
}
.lineage-summary-grid span,
.lineage-summary-grid strong,
.lineage-summary-grid small {
display: block;
}
.lineage-summary-grid span {
color: var(--muted);
}
.lineage-summary-grid strong {
margin: 7px 0 4px;
color: var(--ink);
font-size: 16px;
}
.lineage-summary-grid article.warning strong {
color: #9a6515;
}
.lineage-summary-grid article.ready strong {
color: var(--green);
}
.lineage-summary-grid small {
color: var(--muted);
line-height: 1.45;
}
.lineage-legend {
display: flex;
align-items: center;
gap: 15px;
margin: 18px 0 9px;
color: var(--muted);
}
.lineage-legend > span {
display: inline-flex;
align-items: center;
gap: 6px;
white-space: nowrap;
}
.lineage-legend i {
width: 11px;
height: 11px;
border: 2px solid var(--green);
border-radius: 3px;
}
.lineage-legend i.optional {
border-color: #6d88a1;
border-style: dashed;
}
.lineage-legend i.gap {
background: var(--amber-soft);
border-color: var(--amber);
}
.lineage-legend small {
margin-left: auto;
text-align: right;
}
.data-lineage-canvas {
padding: 15px;
background:
linear-gradient(rgba(34, 105, 79, 0.035) 1px, transparent 1px),
linear-gradient(90deg, rgba(34, 105, 79, 0.035) 1px, transparent 1px),
#f7f9f7;
background-size: 24px 24px;
border: 1px solid #e1e8e3;
border-radius: 14px;
}
.lineage-stage-grid {
display: grid;
grid-template-columns: minmax(250px, 1.08fr) 48px minmax(210px, 0.82fr) 48px minmax(250px, 1fr);
align-items: start;
gap: 8px;
}
.lineage-stage {
min-width: 0;
overflow: hidden;
background: rgba(255, 255, 255, 0.94);
border: 1px solid #dfe7e1;
border-radius: 12px;
box-shadow: 0 8px 24px rgba(25, 58, 45, 0.06);
}
.lineage-stage-head {
display: flex;
min-height: 45px;
align-items: center;
justify-content: space-between;
gap: 8px;
padding: 10px 12px;
color: var(--green);
background: #edf6f1;
border-bottom: 1px solid #dce9e1;
}
.lineage-stage.topics .lineage-stage-head {
color: #376991;
background: #eef4f9;
border-color: #dae6ef;
}
.lineage-stage.reports .lineage-stage-head {
color: #8b621f;
background: #fff8ea;
border-color: #eee0bd;
}
.lineage-stage-head span {
font-weight: 800;
}
.lineage-stage-head strong {
font-weight: 700;
}
.lineage-stage-list {
display: grid;
gap: 8px;
padding: 9px;
}
.lineage-node {
display: block;
width: 100%;
min-width: 0;
padding: 11px;
color: var(--ink);
background: white;
border: 1px solid #dfe7e1;
border-radius: 10px;
text-align: left;
transition:
transform 0.18s ease,
border-color 0.18s ease,
box-shadow 0.18s ease;
}
.lineage-node:hover,
.lineage-node:focus-visible {
transform: translateY(-1px);
border-color: #8fc2a9;
box-shadow: 0 8px 20px rgba(29, 83, 62, 0.11);
}
.lineage-node.selected {
background: #f3f9f6;
border-color: #78b597;
box-shadow: inset 3px 0 var(--green);
}
.lineage-node.has-gap {
background: #fffcf5;
border-color: #e8d29f;
}
.lineage-node-top {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
margin-bottom: 8px;
}
.lineage-node-top em,
.lineage-node-top i {
padding: 4px 6px;
border-radius: 6px;
font-style: normal;
font-weight: 700;
}
.lineage-node-top em {
color: var(--green);
background: var(--green-soft);
}
.lineage-node-top em.optional {
color: #4e718e;
background: var(--blue-soft);
}
.lineage-node-top i.ready {
color: var(--green);
background: #eff7f2;
}
.lineage-node-top i.gap {
color: #966214;
background: var(--amber-soft);
}
.lineage-node > strong,
.lineage-node > small {
display: block;
}
.lineage-node > strong {
overflow: hidden;
font-size: 14px;
line-height: 1.45;
text-overflow: ellipsis;
}
.lineage-node > small {
min-height: 38px;
margin-top: 5px;
overflow: hidden;
color: var(--muted);
line-height: 1.5;
}
.lineage-node-meta {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
margin-top: 8px;
padding-top: 8px;
color: var(--muted);
border-top: 1px solid #edf0ed;
}
.lineage-node-meta b {
color: var(--green);
}
.lineage-node-gap {
display: block;
margin-top: 7px;
padding: 6px 7px;
overflow: hidden;
color: #8c621b;
background: #fff5db;
border-radius: 6px;
line-height: 1.45;
text-overflow: ellipsis;
}
.lineage-report-node > strong {
white-space: normal;
}
.lineage-report-group {
min-width: 0;
overflow: hidden;
background: white;
border: 1px solid #e2e7e3;
border-radius: 9px;
}
.lineage-report-group > summary {
display: grid;
grid-template-columns: minmax(0, 1fr) auto 12px;
align-items: center;
gap: 8px;
padding: 10px;
color: var(--ink);
background: #fafbf9;
cursor: pointer;
list-style: none;
}
.lineage-report-group > summary::-webkit-details-marker {
display: none;
}
.lineage-report-group > summary::after {
width: 7px;
height: 7px;
border-right: 2px solid #819088;
border-bottom: 2px solid #819088;
content: "";
transform: rotate(45deg) translateY(-2px);
transition: transform 0.16s ease;
}
.lineage-report-group[open] > summary::after {
transform: rotate(225deg) translate(-2px, -1px);
}
.lineage-report-group > summary span,
.lineage-report-group > summary strong,
.lineage-report-group > summary small {
display: block;
min-width: 0;
}
.lineage-report-group > summary small {
margin-top: 3px;
color: var(--muted);
}
.lineage-report-group > summary em {
padding: 4px 6px;
color: #805b16;
background: var(--amber-soft);
border-radius: 6px;
font-style: normal;
font-weight: 700;
white-space: nowrap;
}
.lineage-report-group-list {
display: grid;
max-height: 360px;
gap: 7px;
padding: 8px;
overflow-y: auto;
border-top: 1px solid #e8ede9;
}
.lineage-topic-node {
display: grid;
grid-template-columns: 30px minmax(0, 1fr);
gap: 3px 9px;
padding: 10px;
background: #f8fbfd;
border: 1px solid #dfe8ef;
border-radius: 9px;
}
.lineage-topic-node > span {
display: grid;
width: 30px;
height: 30px;
grid-row: 1 / 3;
place-items: center;
color: #467594;
background: #e5f0f7;
border-radius: 7px;
font-weight: 800;
}
.lineage-topic-node strong {
align-self: end;
line-height: 1.4;
}
.lineage-topic-node small {
color: var(--muted);
line-height: 1.4;
}
.lineage-connector {
display: grid;
min-height: 120px;
align-content: center;
justify-items: center;
gap: 9px;
color: var(--muted);
}
.lineage-connector span {
text-align: center;
}
.lineage-connector i {
position: relative;
display: block;
width: 38px;
height: 2px;
background: #9fb2a8;
}
.lineage-connector i::after {
position: absolute;
top: -4px;
right: -1px;
width: 8px;
height: 8px;
border-top: 2px solid #789286;
border-right: 2px solid #789286;
content: "";
transform: rotate(45deg);
}
.lineage-connector b {
position: absolute;
top: -3px;
left: 4px;
width: 8px;
height: 8px;
background: var(--lime);
border: 2px solid white;
border-radius: 50%;
box-shadow: 0 0 0 1px #9fb2a8;
}
.lineage-empty-node {
display: grid;
min-height: 150px;
place-items: center;
align-content: center;
gap: 7px;
padding: 20px;
color: var(--muted);
text-align: center;
}
.lineage-empty-node svg {
width: 28px;
height: 28px;
color: #91a49a;
}
.lineage-empty-node strong,
.lineage-empty-node small {
display: block;
}
.lineage-gap-section {
margin-top: 16px;
padding-top: 16px;
border-top: 1px solid var(--line-soft);
}
.lineage-gap-heading {
display: flex;
align-items: end;
justify-content: space-between;
gap: 12px;
margin-bottom: 10px;
}
.lineage-gap-heading span {
color: #ad741d;
font-weight: 800;
letter-spacing: 0.08em;
}
.lineage-gap-heading h3 {
margin: 4px 0 0;
font-size: 16px;
}
.lineage-gap-heading > strong {
padding: 6px 9px;
color: #956313;
background: var(--amber-soft);
border-radius: 7px;
}
.lineage-gap-list {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 9px;
}
.lineage-gap-card {
display: flex;
min-width: 0;
flex-direction: column;
padding: 13px;
background: #fffcf5;
border: 1px solid #ead8ad;
border-radius: 11px;
}
.lineage-gap-card.blocking {
background: #fff8f4;
border-color: #ebc5b5;
}
.lineage-gap-card-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.lineage-gap-card-head span {
display: inline-flex;
align-items: center;
gap: 6px;
color: #a06611;
font-weight: 800;
}
.lineage-gap-card.blocking .lineage-gap-card-head span {
color: #a34f31;
}
.lineage-gap-card-head span i {
width: 7px;
height: 7px;
background: var(--amber);
border-radius: 50%;
}
.lineage-gap-card.blocking .lineage-gap-card-head span i {
background: #c96643;
}
.lineage-gap-card-head em {
color: var(--muted);
font-style: normal;
}
.lineage-gap-card > strong,
.lineage-gap-card > small {
display: block;
}
.lineage-gap-card > strong {
margin-top: 10px;
line-height: 1.5;
}
.lineage-gap-card > small {
margin-top: 4px;
color: var(--muted);
line-height: 1.5;
}
.lineage-gap-fields {
display: flex;
flex-wrap: wrap;
gap: 5px;
margin-top: 9px;
}
.lineage-gap-fields span {
padding: 4px 6px;
color: #81591a;
background: #fff1cb;
border-radius: 5px;
font-family: "SFMono-Regular", Consolas, monospace;
}
.lineage-gap-card.blocking .lineage-gap-fields span {
color: #944a30;
background: #fee9df;
}
.lineage-gap-card p {
margin: 10px 0;
color: var(--ink-soft);
line-height: 1.6;
}
.lineage-gap-card dl {
display: grid;
gap: 6px;
margin: auto 0 10px;
padding: 9px;
background: rgba(255, 255, 255, 0.75);
border-radius: 8px;
}
.lineage-gap-card dl div {
display: grid;
grid-template-columns: 74px minmax(0, 1fr);
gap: 7px;
}
.lineage-gap-card dt {
color: var(--muted);
}
.lineage-gap-card dd {
min-width: 0;
margin: 0;
font-weight: 700;
}
.lineage-gap-card > button {
width: 100%;
min-height: 36px;
color: #8c5d12;
background: white;
border: 1px solid #e3cd9c;
border-radius: 7px;
font-weight: 700;
}
.lineage-gap-card.blocking > button {
color: #9a4d32;
border-color: #e6b8a5;
}
.lineage-gap-card > button:hover {
background: #fff7e5;
}
.lineage-gap-empty {
display: flex;
grid-column: 1 / -1;
min-height: 90px;
align-items: center;
justify-content: center;
gap: 12px;
padding: 18px;
color: var(--muted);
background: #f4f8f5;
border: 1px dashed #cbded2;
border-radius: 11px;
}
.lineage-gap-empty svg {
width: 28px;
height: 28px;
color: var(--green);
}
.lineage-gap-empty strong,
.lineage-gap-empty small {
display: block;
}
.lineage-gap-empty small {
margin-top: 4px;
}
.data-issue-owner-list {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
margin: 12px 0 0;
}
.data-issue-owner-list div {
padding: 10px;
background: #f5f8f5;
border: 1px solid var(--line-soft);
border-radius: 8px;
}
.data-issue-owner-list dt {
color: var(--muted);
}
.data-issue-owner-list dd {
margin: 5px 0 0;
font-weight: 700;
}
.source-filter-toolbar {
display: flex;
align-items: center;
@@ -6397,6 +7231,30 @@ svg {
grid-template-columns: 1fr;
}
.lineage-stage-grid {
grid-template-columns: 1fr;
}
.lineage-stage-list {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.report-direction .lineage-stage.reports .lineage-stage-list {
grid-template-columns: 1fr;
}
.lineage-connector {
min-height: 36px;
}
.lineage-connector i {
transform: rotate(90deg);
}
.lineage-gap-list {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.platform-metric-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
@@ -6487,6 +7345,24 @@ svg {
flex-direction: column;
}
.data-lineage-toolbar {
grid-template-columns: 1fr;
align-items: stretch;
}
.lineage-mode-switch {
display: grid;
grid-template-columns: 1fr 1fr;
}
.lineage-summary-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.lineage-gap-list {
grid-template-columns: 1fr;
}
.tenant-card-grid {
grid-template-columns: 1fr;
}
@@ -6977,6 +7853,54 @@ svg {
width: 100%;
}
.data-lineage-header,
.lineage-gap-heading {
align-items: flex-start;
flex-direction: column;
}
.lineage-snapshot-badge {
align-self: flex-start;
}
.lineage-mode-switch button {
padding: 0 8px;
}
.lineage-summary-grid,
.lineage-stage-list {
grid-template-columns: 1fr;
}
.lineage-legend {
align-items: flex-start;
flex-wrap: wrap;
gap: 8px 12px;
}
.lineage-legend small {
width: 100%;
margin-left: 0;
text-align: left;
}
.data-lineage-canvas {
padding: 10px;
}
.lineage-gap-toggle {
min-height: 34px;
}
.lineage-gap-card dl div {
grid-template-columns: 1fr;
gap: 2px;
}
.data-issue-owner-list {
grid-template-columns: 1fr;
}
.source-license-grid {
grid-template-columns: 1fr;
}