package-current-employee-prep.py 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. """Build a review-only integration handoff. Never installs or touches a gateway."""
  2. from pathlib import Path
  3. from io import BytesIO
  4. import hashlib
  5. import json
  6. import zipfile
  7. ROOT = Path(__file__).resolve().parent.parent
  8. DEST = ROOT / 'work/delivery-by-recipient-20261102'
  9. NAME = 'ksf-current-employee-integration-prep-20261102-v2'
  10. skill = ROOT / 'skills/ksf-workshop-runtime'
  11. payloads = {}
  12. rows = (skill / 'FILES.sha256').read_text(encoding='utf-8').splitlines()
  13. assert len(rows) == 10
  14. for row in rows:
  15. fingerprint, rel = row.split(' ', 1)
  16. b = (skill / rel).read_bytes()
  17. assert hashlib.sha256(b).hexdigest() == fingerprint
  18. payloads['skills/ksf-workshop-runtime/' + rel] = b
  19. payloads['skills/ksf-workshop-runtime/FILES.sha256'] = (skill / 'FILES.sha256').read_bytes()
  20. files = [
  21. 'scripts/install-workshop-skill.mjs',
  22. 'integrations/wecom-identity/workshop_registration.py',
  23. 'integrations/wecom-identity/__init__.py',
  24. 'integrations/wecom-identity/registration.example.json',
  25. 'test/workshop-identity.test.js', 'test/workshop-registration.test.py',
  26. 'docs/wecom-current-employee-registration.md', 'docs/aibot-adapter-v3-review-20261102.md',
  27. ]
  28. for rel in files: payloads[rel] = (ROOT / rel).read_bytes()
  29. # identity JS suite imports runWorkshop, which is part of the skill payload.
  30. for name in ('给运维001-v3复核与接口.txt', '给王刚001-v3阶段回复.txt'):
  31. payloads[name] = (DEST / name).read_bytes()
  32. for rel, b in payloads.items():
  33. assert 'credential-binding' not in rel and not rel.endswith(('.pem', '.key', '.env'))
  34. assert b'-----BEGIN PRIVATE KEY-----' not in b
  35. payloads['FILES.sha256'] = ''.join(hashlib.sha256(payloads[k]).hexdigest() + ' ' + k + chr(10) for k in sorted(payloads)).encode()
  36. memory = BytesIO()
  37. with zipfile.ZipFile(memory, 'w', zipfile.ZIP_DEFLATED) as z:
  38. for rel, b in sorted(payloads.items()):
  39. z.writestr(zipfile.ZipInfo(rel, (2026, 11, 2, 0, 0, 0)), b, compress_type=zipfile.ZIP_DEFLATED)
  40. packed = memory.getvalue()
  41. with zipfile.ZipFile(BytesIO(packed)) as z:
  42. assert z.testzip() is None
  43. for line in z.read('FILES.sha256').decode().splitlines():
  44. fingerprint, rel = line.split(' ', 1)
  45. assert hashlib.sha256(z.read(rel)).hexdigest() == fingerprint
  46. DEST.mkdir(parents=True, exist_ok=True)
  47. target = DEST / (NAME + '.zip')
  48. if target.exists(): assert target.read_bytes() == packed, 'REFUSE_OVERWRITE_DIFFERENT_PACKAGE'
  49. else: target.write_bytes(packed)
  50. receipt = {'file': str(target), 'sizeBytes': len(packed), 'sha256': hashlib.sha256(packed).hexdigest(),
  51. 'outerManifestEntries': len(payloads) - 1, 'skillManifestEntries': len(rows),
  52. 'purpose': 'isolated integration review only', 'installed': False, 'deployed': False, 'containsCredentials': False}
  53. (DEST / (NAME + '.json')).write_text(json.dumps(receipt, ensure_ascii=False, indent=2) + chr(10), encoding='utf-8')
  54. print(json.dumps(receipt, ensure_ascii=False, indent=2))