本卡屬 FR-169(母卡 (建卡後補 Case No)),卡 P1,批 1。只改 jedi-python-package。依賴:無。
整個案子的核心是一支新的小套件 jedi-file-protect,只做三件事:①產一組 16 碼的隨機密碼;②給它檔案內容與檔名,依副檔名決定怎麼加密——PDF 用 PDF 規格內建的 AES-256 開啟密碼、Word/Excel 用 Office 內建的密碼加密、其他格式與多檔打成加密 7z(連檔名清單一起藏);③在 PDF 與 Word 頁尾蓋「下載者、時間」小字浮水印。加密完的檔還是正常的 .pdf/.docx/.xlsx,Word、Acrobat、Chrome 雙擊會自己跳密碼框,使用者不用裝任何東西;7z 要用 7-Zip 或 Keka。套件零框架相依(照 jedi-masking 那支的形狀),因為主系統與 Agent 都要裝,Agent 釘的 jedi-common 很舊、裝不進重的東西。政策判斷、稽核、密碼顯示畫面都不在套件裡,那是宿主的事。
new:照 jedi-masking 形狀開一支「一件事、零框架相依」的小套件(只相依 pypdf、msoffcrypto-tool、py7zr、python-docx、cryptography)。既有 cryptography Fernet 是欄位加密不是檔案加密,不適用;既有結案報告「草稿」浮水印是 docx 範本變數,只適用該範本,故套件另提供通用頁尾浮水印。政策、稽核、密碼顯示畫面都不進套件(宿主的事)
repo:~/Projects/Jedicogy/module/jedi-python-package
新開:jedi-file-protect/pyproject.toml
新開:jedi-file-protect/jedi_file_protect/__init__.py
新開:jedi-file-protect/jedi_file_protect/password.py(generate_password:16 碼英數四段、去 0O1lI、`secrets`)
新開:jedi-file-protect/jedi_file_protect/protect.py(protect(data, filename, password, *, watermark=None) → ProtectedFile(data, filename, needs_7zip: bool);依副檔名分派)
新開:jedi-file-protect/jedi_file_protect/pdf.py(pypdf AES-256 R6;禁 RC4/R5)
新開:jedi-file-protect/jedi_file_protect/office.py(msoffcrypto agile 加密 docx/xlsx/pptx)
新開:jedi-file-protect/jedi_file_protect/archive.py(py7zr AES-256、header 加密,多檔與其他副檔名)
新開:jedi-file-protect/jedi_file_protect/watermark.py(PDF 頁尾小字、docx 頁尾小字)
新開:jedi-file-protect/tests/
新開:jedi-file-protect/README.md
新開:jedi-file-protect/publish.sh
jedi-masking/ 形狀開 jedi-file-protect/:pyproject.toml(相依只有 pypdf>=5、msoffcrypto-tool>=5.4、py7zr>=0.22、python-docx、cryptography;不得出現 Flask/SQLAlchemy/jedi-common)、publish.sh、README.md、tests/。password.py:generate_password() -> str,secrets.choice 從去掉 0O1lI 的英數字母表取 16 碼,每 4 碼以 - 相連(19 字元)。禁 random。pdf.py:pypdf.PdfWriter.encrypt(user_password=pw, owner_password=None, algorithm="AES-256")——是 R6;AES-256-R5 與 RC4-* 禁用,測試斷言 /Encrypt 的 /R == 6。office.py:msoffcrypto.format.ooxml.OOXMLFile 的 encrypt(password, outfile)(agile 加密);只收 .docx/.xlsx/.pptx,舊 .doc/.xls 拋 UnsupportedFormat。archive.py:py7zr.SevenZipFile(buf, 'w', password=pw, header_encryption=True);輸入 list[(name, bytes)];單一非文件檔也走這裡(回 <原檔名>.7z)。watermark.py:PDF 用 pypdf 每頁疊一個頁尾文字 overlay(reportlab 若需要就加相依,不要用 LibreOffice);docx 用 python-docx 在 footer 加一段。字串格式 {nickname}({login}) · {YYYY-MM-DD HH:mm} · Guidant AI。protect.py:protect(data, filename, password, *, watermark=None) -> ProtectedFile(data, filename, needs_7zip, encrypted);分派表放模組頂端常數,不寫 if 鏈;多檔走 protect_many(files, archive_name, password)。/R==6 紅;把 header_encryption 改 False → 「不帶密碼列檔名要失敗」紅。套件 tests:pdf 加密後 pypdf 不帶密碼開啟 raise、帶密碼開啟成功且 /R 為 6;docx/xlsx 加密後 msoffcrypto 回 is_encrypted() True 且用密碼解回原 bytes;7z 不帶密碼 py7zr 列檔名 raise(header 加密);password 1 萬次無 0O1lI、長度 19、四段;突變:把 pdf 改 R5 測試紅、把 7z header 加密拿掉測試紅;pip show 相依不含 Flask/SQLAlchemy;浮水印:PDF 每頁最後一行含下載者字串、docx footer 含同字串