Prepare password-free inbound-library IMAP entry for attended custody
Sibling of the telemetry SMTP entry for library@coulomb.social (inbound-library ILIB-WP-0002-T07). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 1170398@bnt-lap001 Assistant-Session: 622cd705-cb31-4322-ba08-dd42e44fa583
This commit is contained in:
parent
6217eef2c4
commit
01e0576132
3 changed files with 162 additions and 0 deletions
55
scripts/inbound_library_imap_entry.py
Normal file
55
scripts/inbound_library_imap_entry.py
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Silent attended creation of a password-free inbound-library IMAP KV entry.
|
||||
|
||||
Never overwrite an existing version, including a password subsequently added by
|
||||
its owner. Run inside warden's attended OpenBao platform-admin login envelope.
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
PATH = 'platform/workloads/inbound-library/imap'
|
||||
FIELDS = {'IMAP_HOST': 'imap.ionos.de', 'IMAP_PORT': '993',
|
||||
'IMAP_USERNAME': 'library@coulomb.social',
|
||||
'IMAP_TLS': 'implicit', 'IMAP_FOLDER': 'INBOX'}
|
||||
|
||||
|
||||
def command(args):
|
||||
return subprocess.run(['bao', *args], capture_output=True, timeout=30)
|
||||
|
||||
|
||||
def run(invoke=command):
|
||||
# Read only metadata before CAS=0 creation. No existing credential value is
|
||||
# needed to refuse an overwrite. The owner can safely rerun after adding it.
|
||||
before = invoke(['kv', 'metadata', 'get', '-format=json', PATH])
|
||||
if before.returncode == 0:
|
||||
metadata = json.loads(before.stdout)['data']
|
||||
if type(metadata.get('current_version')) is int and metadata['current_version'] >= 1:
|
||||
return 0
|
||||
return 20
|
||||
# Never infer absence from arbitrary errors or an unauthenticated connection.
|
||||
if b'No value found at ' not in before.stderr + before.stdout:
|
||||
return 21
|
||||
created = invoke(['kv', 'put', '-format=json', '-cas=0', PATH,
|
||||
*[key + '=' + value for key, value in FIELDS.items()]])
|
||||
if created.returncode:
|
||||
return 22
|
||||
if json.loads(created.stdout).get('data', {}).get('version') != 1:
|
||||
return 23
|
||||
after = invoke(['kv', 'metadata', 'get', '-format=json', PATH])
|
||||
if after.returncode or json.loads(after.stdout)['data'].get('current_version') != 1:
|
||||
return 24
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# The attended lane refuses all child output, including exceptions.
|
||||
with open(os.devnull, 'w') as sink:
|
||||
os.dup2(sink.fileno(), 1)
|
||||
os.dup2(sink.fileno(), 2)
|
||||
try:
|
||||
status = run()
|
||||
except Exception:
|
||||
status = 25
|
||||
sys.exit(status)
|
||||
Loading…
Add table
Add a link
Reference in a new issue