2026-08-16 20:27:52 +08:00
#!/usr/bin/env python3
""" HoloLake enterprise identity, relationship and responsibility receipt service.
The service binds only to loopback . Nginx exposes exact routes . Credentials are
verified against the local Forgejo API and are never stored or logged .
"""
from __future__ import annotations
import base64
2026-08-16 20:49:13 +08:00
import http . cookiejar
2026-08-16 20:27:52 +08:00
import hashlib
import hmac
import json
import os
import re
import sqlite3
import time
import urllib . error
import urllib . parse
import urllib . request
import uuid
from http . server import BaseHTTPRequestHandler , ThreadingHTTPServer
from pathlib import Path
BIND = os . environ . get ( " GH_ENTERPRISE_IDENTITY_BIND " , " 127.0.0.1 " )
PORT = int ( os . environ . get ( " GH_ENTERPRISE_IDENTITY_PORT " , " 8032 " ) )
DB_PATH = os . environ . get (
" GH_ENTERPRISE_IDENTITY_DB " ,
" /var/lib/guanghu-enterprise-identity/identity.sqlite3 " ,
)
REGISTRY_PATH = os . environ . get (
" GH_ENTERPRISE_IDENTITY_REGISTRY " ,
" /etc/guanghu/enterprise-identity-registry.json " ,
)
FORGEJO_USER_API = os . environ . get (
" GH_ENTERPRISE_FORGEJO_USER_API " , " http://127.0.0.1:3341/api/v1/user "
)
2026-08-16 20:49:13 +08:00
FORGEJO_WEB_BASE = os . environ . get (
" GH_ENTERPRISE_FORGEJO_WEB_BASE " , " https://guanghu.chat/code "
) . rstrip ( " / " )
2026-08-17 00:16:24 +08:00
FORGEJO_API_BASE = os . environ . get (
" GH_ENTERPRISE_FORGEJO_API_BASE " , " http://127.0.0.1:3341/api/v1 "
) . rstrip ( " / " )
2026-08-16 20:27:52 +08:00
RECEIPT_KEY = os . environ . get ( " GH_ENTERPRISE_RECEIPT_KEY " , " " )
MAX_BODY = 16_384
USERNAME = re . compile ( r " ^[A-Za-z0-9_-] { 1,40}$ " )
DECISIONS = { " ACCEPT " , " REJECT " , " DEFER " , " ACCEPT_WITH_CHANGES " }
def now ( ) - > int :
return int ( time . time ( ) )
def canonical ( value : object ) - > bytes :
return json . dumps ( value , ensure_ascii = False , sort_keys = True , separators = ( " , " , " : " ) ) . encode ( )
def load_registry ( ) - > dict :
registry = json . loads ( Path ( REGISTRY_PATH ) . read_text ( encoding = " utf-8 " ) )
if registry . get ( " schema " ) != " guanghu.enterprise-identity-registry/v1 " :
raise ValueError ( " enterprise identity registry schema invalid " )
humans = registry . get ( " humans " )
if not isinstance ( humans , list ) or not humans :
raise ValueError ( " enterprise identity registry is empty " )
numbers = [ item . get ( " human_number " ) for item in humans ]
usernames = [ item . get ( " username " ) for item in humans ]
if len ( numbers ) != len ( set ( numbers ) ) or len ( usernames ) != len ( set ( usernames ) ) :
raise ValueError ( " enterprise identity registry identities must be unique " )
for item in humans :
if not USERNAME . fullmatch ( str ( item . get ( " username " , " " ) ) ) :
raise ValueError ( " enterprise username invalid " )
for persona in item . get ( " personas " , [ ] ) :
if persona . get ( " species " ) != " AGE " or str ( persona . get ( " current_persona_identity " , " " ) ) . startswith ( " AGE- " ) :
raise ValueError ( " AGE is a species and cannot be used as a persona identity number " )
return registry
def database ( ) - > sqlite3 . Connection :
path = Path ( DB_PATH )
path . parent . mkdir ( parents = True , exist_ok = True )
db = sqlite3 . connect ( path )
db . row_factory = sqlite3 . Row
db . executescript (
"""
PRAGMA journal_mode = WAL ;
PRAGMA foreign_keys = ON ;
CREATE TABLE IF NOT EXISTS relationship_receipts (
receipt_id TEXT PRIMARY KEY ,
idempotency_key TEXT NOT NULL UNIQUE ,
human_number TEXT NOT NULL ,
username TEXT NOT NULL ,
registry_version TEXT NOT NULL ,
decision TEXT NOT NULL ,
observed_at INTEGER NOT NULL ,
receipt_hash TEXT NOT NULL ,
receipt_signature TEXT NOT NULL
) ;
CREATE TABLE IF NOT EXISTS responsibility_receipts (
receipt_id TEXT PRIMARY KEY ,
idempotency_key TEXT NOT NULL UNIQUE ,
human_number TEXT NOT NULL ,
username TEXT NOT NULL ,
responsibility_domain TEXT NOT NULL ,
responsibility_version TEXT NOT NULL ,
decision TEXT NOT NULL ,
note TEXT NOT NULL ,
observed_at INTEGER NOT NULL ,
receipt_hash TEXT NOT NULL ,
receipt_signature TEXT NOT NULL
) ;
2026-08-16 20:49:13 +08:00
CREATE TABLE IF NOT EXISTS credential_rotation_receipts (
receipt_id TEXT PRIMARY KEY ,
human_number TEXT NOT NULL ,
username TEXT NOT NULL ,
observed_at INTEGER NOT NULL ,
receipt_hash TEXT NOT NULL ,
receipt_signature TEXT NOT NULL
) ;
2026-08-16 20:27:52 +08:00
CREATE TABLE IF NOT EXISTS audit (
sequence INTEGER PRIMARY KEY AUTOINCREMENT ,
observed_at INTEGER NOT NULL ,
kind TEXT NOT NULL ,
human_number_hash TEXT NOT NULL ,
receipt_id TEXT NOT NULL
) ;
"""
)
return db
def find_human ( registry : dict , number : str ) - > dict | None :
encoded = number . encode ( " utf-8 " )
return next (
(
item
for item in registry [ " humans " ]
if hmac . compare_digest ( item [ " human_number " ] . encode ( " utf-8 " ) , encoded )
) ,
None ,
)
def parse_basic ( header : str ) - > tuple [ str , str ] | None :
if not header . startswith ( " Basic " ) :
return None
try :
decoded = base64 . b64decode ( header [ 6 : ] , validate = True ) . decode ( " utf-8 " )
username , password = decoded . split ( " : " , 1 )
except ( ValueError , UnicodeDecodeError ) :
return None
if not USERNAME . fullmatch ( username ) or not password or len ( password ) > 512 :
return None
return username , password
def verify_forgejo ( username : str , password : str ) - > bool :
request = urllib . request . Request ( FORGEJO_USER_API )
credential = base64 . b64encode ( f " { username } : { password } " . encode ( ) ) . decode ( )
request . add_header ( " Authorization " , f " Basic { credential } " )
request . add_header ( " Accept " , " application/json " )
try :
with urllib . request . urlopen ( request , timeout = 10 ) as response :
body = json . load ( response )
return response . status == 200 and hmac . compare_digest ( str ( body . get ( " login " , " " ) ) , username )
except ( urllib . error . HTTPError , urllib . error . URLError , TimeoutError , ValueError ) :
return False
2026-08-16 20:49:13 +08:00
def rotate_forgejo_password ( username : str , current_password : str , new_password : str ) - > bool :
""" Use Forgejo ' s own first-login session to rotate a forced-change password.
This needs no standing admin token : the old credential opens a normal user
session and Forgejo itself admits only the forced password - change form .
"""
jar = http . cookiejar . CookieJar ( )
opener = urllib . request . build_opener ( urllib . request . HTTPCookieProcessor ( jar ) )
try :
opener . open ( FORGEJO_WEB_BASE + " /user/login " , timeout = 15 ) . read ( )
login = urllib . parse . urlencode (
{ " user_name " : username , " password " : current_password }
) . encode ( )
login_request = urllib . request . Request (
FORGEJO_WEB_BASE + " /user/login " , data = login
)
login_request . add_header ( " Content-Type " , " application/x-www-form-urlencoded " )
with opener . open ( login_request , timeout = 15 ) as response :
response . read ( )
if not urllib . parse . urlparse ( response . geturl ( ) ) . path . endswith (
" /user/settings/change_password "
) :
return False
change = urllib . parse . urlencode (
{ " password " : new_password , " retype " : new_password }
) . encode ( )
change_request = urllib . request . Request (
FORGEJO_WEB_BASE + " /user/settings/change_password " , data = change
)
change_request . add_header ( " Content-Type " , " application/x-www-form-urlencoded " )
with opener . open ( change_request , timeout = 15 ) as response :
response . read ( )
return verify_forgejo ( username , new_password )
except ( urllib . error . HTTPError , urllib . error . URLError , TimeoutError , ValueError ) :
return False
2026-08-16 20:27:52 +08:00
def signed_receipt ( payload : dict ) - > dict :
if len ( RECEIPT_KEY ) < 32 :
raise RuntimeError ( " receipt signing key unavailable " )
body = canonical ( payload )
receipt_hash = hashlib . sha256 ( body ) . hexdigest ( )
signature = hmac . new ( RECEIPT_KEY . encode ( ) , body , hashlib . sha256 ) . hexdigest ( )
return { * * payload , " receipt_hash " : receipt_hash , " receipt_signature " : signature }
2026-08-17 00:16:24 +08:00
def stable_receipt_id ( prefix : str , human_number : str , idempotency_key : str ) - > str :
""" Keep one receipt path across safe client retries without exposing the key. """
material = f " { prefix } \n { human_number } \n { idempotency_key } " . encode ( )
digest = hmac . new ( RECEIPT_KEY . encode ( ) , material , hashlib . sha256 ) . hexdigest ( ) [ : 32 ]
return f " { prefix } - { digest . upper ( ) } "
def repository_receipt_path ( kind : str , receipt_id : str ) - > str :
if kind not in { " relationship " , " responsibility " } or not re . fullmatch (
r " GH-(?:REL|RESP)-[A-F0-9] {32} " , receipt_id
) :
raise ValueError ( " repository receipt path input invalid " )
return f " .guanghu/receipts/ { kind } / { receipt_id } .json "
def project_receipt_to_repository (
human : dict , username : str , password : str , kind : str , receipt : dict
) - > dict :
""" Commit a signed receipt with the human ' s own Forgejo authority.
No administrator token or server - side repository credential is held . A
retry that finds the deterministic path already present must read back the
exact bytes before treating the projection as idempotent .
"""
repository = str ( human [ " repository " ] )
if repository . split ( " / " , 1 ) [ 0 ] != username :
raise RuntimeError ( " repository owner does not match authenticated user " )
path = repository_receipt_path ( kind , str ( receipt [ " receipt_id " ] ) )
endpoint = (
f " { FORGEJO_API_BASE } /repos/ { urllib . parse . quote ( repository , safe = ' / ' ) } "
f " /contents/ { urllib . parse . quote ( path , safe = ' / ' ) } "
)
content = canonical ( receipt ) + b " \n "
authorization = " Basic " + base64 . b64encode ( f " { username } : { password } " . encode ( ) ) . decode ( )
create_body = canonical (
{
" branch " : " main " ,
" content " : base64 . b64encode ( content ) . decode ( ) ,
" message " : f " receipt( { kind } ): { receipt [ ' receipt_id ' ] } " ,
}
)
request = urllib . request . Request ( endpoint , data = create_body , method = " POST " )
request . add_header ( " Authorization " , authorization )
request . add_header ( " Accept " , " application/json " )
request . add_header ( " Content-Type " , " application/json " )
try :
with urllib . request . urlopen ( request , timeout = 15 ) as response :
result = json . load ( response )
if response . status != 201 :
raise RuntimeError ( f " repository projection returned { response . status } " )
commit = str ( result . get ( " commit " , { } ) . get ( " sha " , " " ) )
if not re . fullmatch ( r " [0-9a-f] { 40,64} " , commit ) :
raise RuntimeError ( " repository projection commit missing " )
return {
" state " : " COMMITTED " ,
" repository " : repository ,
" path " : path ,
" commit " : commit ,
}
except urllib . error . HTTPError as error :
if error . code != 422 :
raise RuntimeError ( f " repository projection failed: { error . code } " ) from error
read_request = urllib . request . Request ( endpoint + " ?ref=main " )
read_request . add_header ( " Authorization " , authorization )
read_request . add_header ( " Accept " , " application/json " )
try :
with urllib . request . urlopen ( read_request , timeout = 15 ) as response :
existing = json . load ( response )
except ( urllib . error . HTTPError , urllib . error . URLError , TimeoutError , ValueError ) as error :
raise RuntimeError ( " repository projection readback failed " ) from error
try :
existing_content = base64 . b64decode ( str ( existing [ " content " ] ) , validate = True )
except ( KeyError , ValueError ) as error :
raise RuntimeError ( " repository projection readback invalid " ) from error
if not hmac . compare_digest ( existing_content , content ) :
raise RuntimeError ( " repository receipt path already contains different bytes " )
return {
" state " : " IDEMPOTENT_READBACK " ,
" repository " : repository ,
" path " : path ,
" commit " : str ( existing . get ( " sha " , " " ) ) ,
}
2026-08-16 20:27:52 +08:00
def public_projection ( registry : dict , human : dict , db : sqlite3 . Connection | None = None ) - > dict :
projection = {
" status " : " RESOLVED " ,
" canonical_id " : human [ " human_number " ] ,
" subject " : {
" id " : human [ " human_number " ] ,
" name " : human [ " display_name " ] ,
" domain " : human [ " responsibility_domain " ] ,
} ,
" work_entry " : {
" domain " : registry [ " work_entry_domain " ] ,
" channel " : registry [ " work_entry_channel " ] ,
} ,
" repository_binding " : {
" host " : " guanghu.chat " ,
" username " : human [ " username " ] ,
" repository " : human [ " repository " ] ,
" private " : True ,
} ,
" persona_relationships " : human [ " personas " ] ,
" persona_identity_governance " : registry [ " persona_identity_governance " ] ,
" registry_version " : registry [ " version " ] ,
}
if db is not None :
relationship = db . execute (
" SELECT decision,observed_at,receipt_hash FROM relationship_receipts WHERE human_number=? ORDER BY observed_at DESC LIMIT 1 " ,
( human [ " human_number " ] , ) ,
) . fetchone ( )
responsibility = db . execute (
" SELECT decision,observed_at,receipt_hash,responsibility_version FROM responsibility_receipts WHERE human_number=? ORDER BY observed_at DESC LIMIT 1 " ,
( human [ " human_number " ] , ) ,
) . fetchone ( )
projection [ " relationship_confirmation " ] = dict ( relationship ) if relationship else None
projection [ " responsibility_receipt " ] = dict ( responsibility ) if responsibility else None
return projection
class Handler ( BaseHTTPRequestHandler ) :
server_version = " GuanghuEnterpriseIdentity/1.0 "
def log_message ( self , fmt : str , * args : object ) - > None :
# Never include headers or request bodies in logs.
print ( " [enterprise-identity] " + fmt % args )
def respond ( self , status : int , body : dict ) - > None :
encoded = json . dumps ( body , ensure_ascii = False ) . encode ( )
self . send_response ( status )
self . send_header ( " Content-Type " , " application/json; charset=utf-8 " )
self . send_header ( " Content-Length " , str ( len ( encoded ) ) )
self . send_header ( " Cache-Control " , " no-store " )
self . send_header ( " X-Content-Type-Options " , " nosniff " )
self . end_headers ( )
self . wfile . write ( encoded )
def body ( self ) - > dict :
length = int ( self . headers . get ( " Content-Length " , " 0 " ) )
if length < 1 or length > MAX_BODY :
raise ValueError ( " request body size invalid " )
value = json . loads ( self . rfile . read ( length ) . decode ( ) )
if not isinstance ( value , dict ) :
raise ValueError ( " JSON object required " )
return value
2026-08-17 00:16:24 +08:00
def authenticated_human ( self , registry : dict , payload : dict ) - > tuple [ dict , str , str ] | None :
2026-08-16 20:27:52 +08:00
credentials = parse_basic ( self . headers . get ( " Authorization " , " " ) )
number = str ( payload . get ( " human_number " , " " ) )
human = find_human ( registry , number )
if not credentials or not human :
return None
username , password = credentials
if not hmac . compare_digest ( username , human [ " username " ] ) or not verify_forgejo ( username , password ) :
return None
2026-08-17 00:16:24 +08:00
return human , username , password
2026-08-16 20:27:52 +08:00
def do_GET ( self ) - > None :
try :
registry = load_registry ( )
except ( OSError , ValueError , json . JSONDecodeError ) as error :
return self . respond ( 503 , { " ok " : False , " error " : f " registry unavailable: { error } " } )
parsed = urllib . parse . urlparse ( self . path )
if parsed . path == " /health " :
return self . respond ( 200 , { " ok " : True , " service " : " guanghu-enterprise-identity " , " registry_version " : registry [ " version " ] , " age_species " : " AGE " , " valid_age_individual_numbers " : 0 } )
if parsed . path == " /v1/resolve " :
number = urllib . parse . parse_qs ( parsed . query ) . get ( " id " , [ " " ] ) [ 0 ]
human = find_human ( registry , number )
return self . respond ( 200 if human else 404 , public_projection ( registry , human ) if human else { " status " : " NOT_FOUND " } )
return self . respond ( 404 , { " ok " : False , " error " : " not found " } )
def do_POST ( self ) - > None :
try :
registry = load_registry ( )
payload = self . body ( )
except ( OSError , ValueError , json . JSONDecodeError ) as error :
return self . respond ( 400 , { " ok " : False , " error " : str ( error ) } )
2026-08-16 20:49:13 +08:00
if self . path == " /v1/change-password " :
credentials = parse_basic ( self . headers . get ( " Authorization " , " " ) )
human = find_human ( registry , str ( payload . get ( " human_number " , " " ) ) )
new_password = str ( payload . get ( " new_password " , " " ) )
if not credentials or not human :
return self . respond ( 401 , { " ok " : False , " error " : " enterprise account authentication failed " } )
username , current_password = credentials
if not hmac . compare_digest ( username , human [ " username " ] ) :
return self . respond ( 401 , { " ok " : False , " error " : " enterprise account authentication failed " } )
if (
len ( new_password ) < 14
or len ( new_password ) > 128
or hmac . compare_digest ( current_password , new_password )
or new_password . isdigit ( )
or new_password . isalpha ( )
) :
return self . respond ( 400 , { " ok " : False , " error " : " new password does not meet the first-login policy " } )
if not rotate_forgejo_password ( username , current_password , new_password ) :
return self . respond ( 401 , { " ok " : False , " error " : " first-login password rotation failed " } )
observed = now ( )
receipt_id = " GH-CRED- " + uuid . uuid4 ( ) . hex . upper ( )
receipt = signed_receipt ( {
" receipt_id " : receipt_id ,
" human_number " : human [ " human_number " ] ,
" username " : username ,
" observed_at " : observed ,
" password_changed " : True ,
} )
db = database ( )
try :
db . execute (
" INSERT INTO credential_rotation_receipts VALUES (?,?,?,?,?,?) " ,
( receipt_id , human [ " human_number " ] , username , observed , receipt [ " receipt_hash " ] , receipt [ " receipt_signature " ] ) ,
)
db . execute (
" INSERT INTO audit(observed_at,kind,human_number_hash,receipt_id) VALUES (?,?,?,?) " ,
( observed , " CREDENTIAL_ROTATION " , hashlib . sha256 ( human [ " human_number " ] . encode ( ) ) . hexdigest ( ) , receipt_id ) ,
)
db . commit ( )
finally :
db . close ( )
return self . respond ( 200 , { " ok " : True , " receipt " : receipt } )
2026-08-16 20:27:52 +08:00
authenticated = self . authenticated_human ( registry , payload )
if not authenticated :
return self . respond ( 401 , { " ok " : False , " error " : " enterprise account authentication failed " } )
2026-08-17 00:16:24 +08:00
human , username , password = authenticated
2026-08-16 20:27:52 +08:00
idempotency_key = str ( payload . get ( " idempotency_key " , " " ) )
if not re . fullmatch ( r " [A-Za-z0-9_-] { 16,96} " , idempotency_key ) :
return self . respond ( 400 , { " ok " : False , " error " : " valid idempotency_key required " } )
db = database ( )
try :
if self . path == " /v1/relationship-confirmations " :
decision = str ( payload . get ( " decision " , " " ) )
if decision not in { " CONFIRM " , " REJECT " } :
return self . respond ( 400 , { " ok " : False , " error " : " relationship decision invalid " } )
existing = db . execute ( " SELECT * FROM relationship_receipts WHERE idempotency_key=? " , ( idempotency_key , ) ) . fetchone ( )
if existing :
return self . respond ( 200 , { " ok " : True , " idempotent " : True , " receipt " : dict ( existing ) } )
observed = now ( )
2026-08-17 00:16:24 +08:00
receipt_id = stable_receipt_id ( " GH-REL " , human [ " human_number " ] , idempotency_key )
2026-08-16 20:27:52 +08:00
receipt = signed_receipt ( { " receipt_id " : receipt_id , " human_number " : human [ " human_number " ] , " username " : username , " registry_version " : registry [ " version " ] , " decision " : decision , " observed_at " : observed } )
2026-08-17 00:16:24 +08:00
try :
projection = project_receipt_to_repository ( human , username , password , " relationship " , receipt )
except RuntimeError as error :
return self . respond ( 503 , { " ok " : False , " error " : str ( error ) } )
2026-08-16 20:27:52 +08:00
db . execute ( " INSERT INTO relationship_receipts VALUES (?,?,?,?,?,?,?,?,?) " , ( receipt_id , idempotency_key , human [ " human_number " ] , username , registry [ " version " ] , decision , observed , receipt [ " receipt_hash " ] , receipt [ " receipt_signature " ] ) )
db . execute ( " INSERT INTO audit(observed_at,kind,human_number_hash,receipt_id) VALUES (?,?,?,?) " , ( observed , " RELATIONSHIP_CONFIRMATION " , hashlib . sha256 ( human [ " human_number " ] . encode ( ) ) . hexdigest ( ) , receipt_id ) )
db . commit ( )
2026-08-17 00:16:24 +08:00
return self . respond ( 201 , { " ok " : True , " receipt " : receipt , " repository_projection " : projection } )
2026-08-16 20:27:52 +08:00
if self . path == " /v1/responsibility-receipts " :
decision = str ( payload . get ( " decision " , " " ) )
note = str ( payload . get ( " note " , " " ) ) [ : 1000 ]
version = str ( payload . get ( " responsibility_version " , " " ) )
if decision not in DECISIONS or not re . fullmatch ( r " [0-9] {4} -[0-9] {2} -[0-9] {2} \ .[0-9]+ " , version ) :
return self . respond ( 400 , { " ok " : False , " error " : " responsibility decision or version invalid " } )
existing = db . execute ( " SELECT * FROM responsibility_receipts WHERE idempotency_key=? " , ( idempotency_key , ) ) . fetchone ( )
if existing :
return self . respond ( 200 , { " ok " : True , " idempotent " : True , " receipt " : dict ( existing ) } )
observed = now ( )
2026-08-17 00:16:24 +08:00
receipt_id = stable_receipt_id ( " GH-RESP " , human [ " human_number " ] , idempotency_key )
2026-08-16 20:27:52 +08:00
receipt = signed_receipt ( { " receipt_id " : receipt_id , " human_number " : human [ " human_number " ] , " username " : username , " responsibility_domain " : human [ " responsibility_domain " ] , " responsibility_version " : version , " decision " : decision , " note " : note , " observed_at " : observed } )
2026-08-17 00:16:24 +08:00
try :
projection = project_receipt_to_repository ( human , username , password , " responsibility " , receipt )
except RuntimeError as error :
return self . respond ( 503 , { " ok " : False , " error " : str ( error ) } )
2026-08-16 20:27:52 +08:00
db . execute ( " INSERT INTO responsibility_receipts VALUES (?,?,?,?,?,?,?,?,?,?,?) " , ( receipt_id , idempotency_key , human [ " human_number " ] , username , human [ " responsibility_domain " ] , version , decision , note , observed , receipt [ " receipt_hash " ] , receipt [ " receipt_signature " ] ) )
db . execute ( " INSERT INTO audit(observed_at,kind,human_number_hash,receipt_id) VALUES (?,?,?,?) " , ( observed , " RESPONSIBILITY_RECEIPT " , hashlib . sha256 ( human [ " human_number " ] . encode ( ) ) . hexdigest ( ) , receipt_id ) )
db . commit ( )
2026-08-17 00:16:24 +08:00
return self . respond ( 201 , { " ok " : True , " receipt " : receipt , " repository_projection " : projection } )
2026-08-16 20:27:52 +08:00
if self . path == " /v1/me/entry " :
return self . respond ( 200 , { " ok " : True , " entry " : public_projection ( registry , human , db ) } )
return self . respond ( 404 , { " ok " : False , " error " : " not found " } )
finally :
db . close ( )
if __name__ == " __main__ " :
load_registry ( )
if len ( RECEIPT_KEY ) < 32 :
raise SystemExit ( " GH_ENTERPRISE_RECEIPT_KEY must contain at least 32 characters " )
ThreadingHTTPServer ( ( BIND , PORT ) , Handler ) . serve_forever ( )