級別:中 依賴:C3(受評範圍 derived from SSP;schema 變動才能拿掉 request fields) 被依賴:C6(FE 表單拿掉)
把專案建立/編輯 API 內的 audit_systems / devices 欄位拿掉(這兩個現在屬 SSP 範疇),保留基本資訊 + 參與人員。Response Schema 對外不變(後端內部已在 C3 改 derived from SSP),FE 表單調整由 C6 處理。
OscalProjectStartRequest(建立專案 request):拿掉 audit_systems + devices 欄位ProjectUpdateRequestSchema(編輯專案 request):拿掉 audit_systems + devices 欄位oscal_project_service.start_oscal_project:移除 Step C(devices INSERT)+ audit_systems INSERT 邏輯GrcProjectService.update_project:移除 Section 3(audit_systems 替換)+ Section 5(devices 替換)邏輯project_device_mapping_service / project_information_system_domain_service(已在 C3 廢,C4 確認 DI 清理)audit_systems / devices(保留,由 C3 改 derive from SSP,API 對外格式不變)/project-devices API(保留 GET,由 C3 改 derive;C3 同步處理 write endpoints 退 410)api/project/serializers/project.py — OscalProjectStartRequest改動前(line 30-51):
class OscalProjectStartRequest(Schema):
profile_uid = fields.String(required=True)
ssp_uid = fields.String(required=False, allow_none=True)
name = fields.String(required=True)
description = fields.String(required=False)
start_date = fields.Date('%Y-%m-%d', allow_none=True)
end_date = fields.Date('%Y-%m-%d', allow_none=True)
owner_uid = fields.String(required=False, allow_none=True, load_default=None)
flow_template_uid = fields.UUID(required=True)
audit_systems = fields.List(
fields.Nested(AuditSystemInputSchema), load_default=[], allow_none=True,
)
participants = fields.List(
fields.Nested(ParticipantInputSchema), load_default=[], allow_none=True,
)
devices = fields.List(
fields.Nested(DeviceInputSchema), load_default=[], allow_none=True,
)改動後:
class OscalProjectStartRequest(Schema):
profile_uid = fields.String(required=True)
ssp_uid = fields.String(required=False, allow_none=True)
name = fields.String(required=True)
description = fields.String(required=False)
start_date = fields.Date('%Y-%m-%d', allow_none=True)
end_date = fields.Date('%Y-%m-%d', allow_none=True)
owner_uid = fields.String(required=False, allow_none=True, load_default=None)
flow_template_uid = fields.UUID(required=True)
participants = fields.List(
fields.Nested(ParticipantInputSchema), load_default=[], allow_none=True,
)
# audit_systems + devices 已移除(C4, 2026-MM-DD)
# 受評範圍改在 SSP 編輯頁維護,見 docs/features/FR-011.3-2605-ssp-edit-in-project/AuditSystemInputSchema / DeviceInputSchema:
OscalProjectStartRequest 拿掉欄位api/grc/serializers/project.py — ProjectUpdateRequestSchema改動前(line 77-112):
class ProjectUpdateRequestSchema(Schema):
name = fields.String(allow_none=True, load_default=None)
description = fields.String(allow_none=True, load_default=None)
start_date = fields.Date(format="%Y-%m-%d", allow_none=True, load_default=None)
end_date = fields.Date(format="%Y-%m-%d", allow_none=True, load_default=None)
status = fields.String(allow_none=True, load_default=None, validate=...)
owner_uid = fields.String(allow_none=True, load_default=None)
audit_systems = fields.List(fields.Nested(_AuditSystemInputSchema), allow_none=True, load_default=None)
participants = fields.List(fields.Nested(_ParticipantInputSchema), allow_none=True, load_default=None)
devices = fields.List(fields.Nested(_DeviceInputSchema), allow_none=True, load_default=None)改動後:
class ProjectUpdateRequestSchema(Schema):
"""PUT /grc/project/<uid> request body.
All fields are optional; only provided fields are updated.
Providing participants as a list (including []) replaces participants entirely.
Omitting (null/missing) leaves it unchanged.
audit_systems + devices 從 C4 (2026-MM-DD) 起移除 — 受評範圍改在 SSP 編輯頁
維護(見 docs/features/FR-011.3-2605-ssp-edit-in-project/)。
"""
name = fields.String(allow_none=True, load_default=None)
description = fields.String(allow_none=True, load_default=None)
start_date = fields.Date(format="%Y-%m-%d", allow_none=True, load_default=None)
end_date = fields.Date(format="%Y-%m-%d", allow_none=True, load_default=None)
status = fields.String(allow_none=True, load_default=None, validate=...)
owner_uid = fields.String(allow_none=True, load_default=None)
participants = fields.List(fields.Nested(_ParticipantInputSchema), allow_none=True, load_default=None)app/project/service/oscal_project_service.py — start_oscal_project改動前(line 456-461):
# Step C — 加入設備
for device in (start_project_dto.devices or []):
self.project_device_mapping_service.add(
project_uid=str(project.uid),
device_uid=device.device_uid,
)改動後:
start_project_dto.devices 和 start_project_dto.audit_systems 屬性已不存在(request schema 拿掉)DI 改動:
__init__ 拿掉 project_device_mapping_service 參數di_containers/project/project_containers.py 對應 wiring 拿掉self.project_device_mapping_service 屬性移除app/grc/service/project_service.py — update_project改動前:
改動後:兩段整段移除
DI 改動:
__init__ 拿掉 project_device_mapping_service + project_information_system_domain_service 參數di_containers/grc/grc_containers.py 對應 wiring 拿掉self._device_mapping_service + self._pis_domain_service 屬性移除/oscal-project/startBefore:
{
"profile_uid": "...",
"name": "稽核 2026",
"flow_template_uid": "...",
"audit_systems": [{"information_system_uid": "..."}],
"devices": [{"device_uid": "..."}],
"participants": [{"user_uid": "...", "role": "auditor"}]
}After:
{
"profile_uid": "...",
"name": "稽核 2026",
"flow_template_uid": "...",
"participants": [{"user_uid": "...", "role": "auditor"}]
}送舊 schema 含 audit_systems / devices 會發生什麼?
Meta.unknown = EXCLUDE 預設 → 忽略未知欄位,建專案成功但 audit_systems / devices 不會被處理Response:原樣(保留 audit_systems + devices 在 ProjectResponseSchema,由 C3 改 derived from SSP)
/grc/project/<uid>同樣行為:移除 request 內 audit_systems / devices,Response 不變。
| 情境 | 行為 |
|---|---|
| FE 還沒同步 deploy,POST 含 audit_systems / devices | unknown=EXCLUDE 忽略,建專案成功,但這些 list 不會寫入 |
| 建專案後 user 直接想看 devices | Response 回 [](C3-Q5 決策),FE 顯示「請至 SSP tab 設定範圍」 |
| 想改舊有專案的 devices | 透過 PUT /grc/project/ |
| 編號 | 問題 | 我建議 |
|---|---|---|
| C4-D1 | request 內舊欄位處理:unknown=EXCLUDE 忽略 vs 直接 reject (ValidationError)? |
EXCLUDE + log warn(向後相容,避免硬撞 FE) |
| C4-D2 | AuditSystemInputSchema / DeviceInputSchema schema class 留還是刪? |
C 階段尾聲確認無 caller 後刪(C4 本期保留,等 C 全綠再清) |
| C4-D3 | ParticipantInputSchema.role 是否限制 manager/reviewer/auditor/viewer?目前用 fields.String 沒 validate |
加 validate.OneOf 比較嚴謹(順手修) |
OscalProjectStartRequest 內無 audit_systems / devicesProjectUpdateRequestSchema 內無 audit_systems / devicesoscal_project_service.start_oscal_project 不再寫 device / audit_systems mappingGrcProjectService.update_project 不再處理 device / audit_systems 替換