o
    pje                     @  s   d Z ddlmZ ddlmZmZ ddlZddlmZmZm	Z	m
Z
mZmZ ddlmZ ddlmZ ddlmZmZmZmZ dd	lmZmZmZmZ dd
lmZ ddlmZ ddlm Z  ddl!m"Z"m#Z#m$Z$ ddl%m&Z&m'Z'm(Z( ddlm)Z) ddl*m+Z+m,Z, ddl-m.Z. ddl/m0Z0m1Z1 ddl2m3Z3 ddl4m5Z5m6Z6m7Z7 ddl8m9Z9m:Z: ddl;m<Z<m=Z= ddl>m?Z? ddl@mAZA ddlBmCZCmDZD edeEddZFe9dZGeFHddd  ZIeFHd!d"d# ZJeFKd$d%d& ZLeFHd'd(d) ZMdd*d+drd6d7ZNeFHd8d9d: ZOeFHd;dsd=d>ZPdtdBdCZQeFKdDdudFdGZReFHdHdIdJ ZSeFHdKdvdMdNZTeFUdKdvdOdPZVeFWdQdwdSdTZXeFHdUdVdW ZYeFHdXdxdZd[ZZdyd]d^Z[eFHd_d`da Z\eFHdbdcdd Z]eFHdedfdg Z^eFHdhdidj Z_eFKdkdldm Z`eFKdndzdpdqZadS ){z?Small authenticated API used to validate platform connectivity.    )annotations)datetimetimezoneN)	Blueprintcurrent_appgjsonifyrequest	send_file)select)SQLAlchemyError)AuthenticationErrorauthenticate_requestread_bootstrap_public_keyrequire_scope)describe_siteregister_bootstrap_siterevoke_signing_keyrotate_signing_key)get_effective_entitlements)usage_snapshot)get_storage_snapshot)BillingWebhookErrorprocess_eventverify_signature)stripe_readinesstranslate_stripe_eventverify_stripe_signature)subscription_allows_app)AppContractErrorload_manifest)manifest_tools)AgentResolutionErrorresolve_instruction)OpenAIToolSelector)filter_profile_toolsget_profilelist_profiles)get_platform_loggerlog_structured)SecretConfigurationErrorSecretIntegrityError)SecretsManager)get_control_plane_session)WordPressBridgeReleaseWordPressPackageReleaseplatform_apiz/api/v1/platform)
url_prefixagent_runtimez/agent/profilesc               
   C  s   zt t} t| d t| j| j}W n9 ty/ } ztdt|ddfW  Y d }~S d }~w t	yK } ztdt|ddfW  Y d }~S d }~ww tddd |D d	S )
Nplatform:agent:tools:readerrorstatusmessage    okc                 S  s   g | ]}|  qS  )to_dict).0profiler;   r;   'bridge_platform/gateway/platform_api.py
<listcomp><       z"agent_profiles.<locals>.<listcomp>)r6   profiles)
r   r	   r   r'   	tenant_idrolesr   r   strPermissionError)identityrB   excr;   r;   r?   agent_profiles2   s   
""rI   z/agent/statusc               
   C  s   zt t} t| d t }W n9 ty, } ztdt|ddfW  Y d }~S d }~w tyH } ztdt|ddfW  Y d }~S d }~ww tddd|d u|d urVd	nd |d ur^|j	nd d
ddS )Nr3   r4   r5   r8   r9   r:   hybridTopenaigateway_validated)modedeterministic_enabledllm_enabledllm_provider	llm_modelexecution_policy)r6   runtime)
r   r	   r   r$   from_environmentr   r   rE   rF   model)rG   selectorrH   r;   r;   r?   agent_runtime_status?   s*   
""rW   z/agent/resolvec                  C  s  zst t} t| d tjddpi }t|trt|dts$tddt|dp+d	 }t
| j|| j}t| jd	|| jd
}tt }t|d || j| j| j||jdt d}ttd| j| j| j|d |j|d |d	 W nY ty } ztdt|ddfW  Y d}~S d}~w ty } ztdt|ddfW  Y d}~S d}~w ty } ztd|jt|dddfW  Y d}~S d}~ww |j|d< |j|d< |j|d< td||dS )zYResolve a basic instruction to a permitted tool call; execution stays on the app gateway.zplatform:agent:invokeTsilentr7   invalid_requestzmessage must be a string	agent_keyabn_assistantFcompactr[   rD   )rC   site_iduser_id
request_idr[   )contextprovideragent_instruction_resolved
capabilityresolver)rC   r_   r`   re   r[   rf   ra   r4   r5   r8   Nr9   )coder7   )r6   r4   i  profile_version	max_stepsr:   )r6   ra   	selection)r   r	   r   get_json
isinstancedictgetrE   r"   stripr&   rC   rD   _tenant_agent_toolsuuiduuid4r#   r_   subjectr[   r$   rT   r)   AGENT_LOGGERr   r   rF   rg   versionri   )rG   payloadr[   r>   toolsra   rj   rH   r;   r;   r?   resolve_agent_instructionV   sf   


""


rx   z/agent/toolsc               
     sH  zGt t} t| d tjdd  tjdd }t| jt  |p&d| j	d} rF fdd|D }|s<t
d	td
|d dW S W nU tyd } ztdt|ddfW  Y d}~S d}~w ty } ztdt|ddfW  Y d}~S d}~w t
y } ztdt|ddfW  Y d}~S d}~ww td
|dS )zBReturn only agent-exposed tools from apps enabled for this tenant.r3   re    r[   Nr]   c                   s   g | ]
}|d   kr|qS re   r;   )r=   toolrz   r;   r?   r@      s    zagent_tools.<locals>.<listcomp>z+Agent capability not found or not availabler:   r   )r6   r{   r4   r5   r8   r9     )r6   rw   )r   r	   r   argsrn   ro   rp   rC   boolrD   LookupErrorr   r   rE   rF   )rG   r[   rw   matchesrH   r;   rz   r?   agent_tools   s4   

"""r   r;   )r[   rD   rC   rE   r^   r~   r[   
str | NonerD   tuple[str, ...]return
list[dict]c                C  s   t | }g }|dg D ].}|dsqztt|dd}W n tttfy,   Y qw |d ur:|t||d q|rFt	t
| |||}t|dd dS )	Nappsenabledapp_idry   )r^   c                 S  s   | d S )Nre   r;   )r{   r;   r;   r?   <lambda>   s    z%_tenant_agent_tools.<locals>.<lambda>)key)r   rn   r    rE   r   ImportErrorModuleNotFoundErrorextendr!   r%   r&   sorted)rC   r^   r[   rD   entitlementsrw   appmanifestr;   r;   r?   rp      s    
rp   z/bridge/releasesc               
   C  sX  zNt t} t| d tjdd}|dvrtdt )}|tt	
t	j|kt	jdt	j  }dd |D }W d    n1 sHw   Y  W nU tyk } ztd	t|d
dfW  Y d }~S d }~w ty } ztd	t|d
dfW  Y d }~S d }~w ty } ztd	t|d
dfW  Y d }~S d }~ww td||dS )Nzplatform:bridge:updates:readchannelstable>   betar   securitydevelopmentzInvalid release channeltest	publishedrevokedc                 S  s   g | ]}t |qS r;   )_bridge_release_payloadr=   releaser;   r;   r?   r@      rA   z-wordpress_bridge_releases.<locals>.<listcomp>r4   r5   r8   r9     r:   )r6   r   releases)r   r	   r   r}   rn   
ValueErrorr-   executer   r.   wherer   r6   in_order_byru   scalarsallr   r   rE   rF   )rG   r   sessionr   rv   rH   r;   r;   r?   wordpress_bridge_releases   s:   

"""r   z#/bridge/releases/<version>/downloadru   c              
   C  sJ  zFt t}t|d t 0}|tttj| ktj	
dtjd  }|d u r/td|j|j}}W d    n1 s@w   Y  W nU tyc } ztdt|ddfW  Y d }~S d }~w ty } ztdt|ddfW  Y d }~S d }~w ty } ztdt|ddfW  Y d }~S d }~ww t|d	d
|d
dS )Nz platform:bridge:updates:downloadr   r   zBridge release not foundr4   r5   r8   r9   r|   application/zipTmimetypeas_attachmentdownload_nameconditional)r   r	   r   r-   r   r   r.   r   ru   r6   r   
revoked_atis_scalar_one_or_noner   artifact_pathartifact_namer   r   rE   rF   r
   )ru   rG   r   r   r   r   rH   r;   r;   r?   download_wordpress_bridge   s:   


	"""r   r   r.   rm   c                 C  s   | j pi }| jd up| jdk}| j| j| j| j| j| j| j	|
d|
d|
ddt|
d|
dg || j|r>d d
S d| j d	d
S )Nr   minimum_wordpress_versionminimum_php_versionschema_version   security_updaterelease_notesz(/api/v1/bridge_platform/bridge/releases/	/download)ru   r   r   artifact_sizesha256	signaturesignature_algorithmr   r   r   r   r   r   revoked_reasondownload_path)metadata_jsonr   r6   ru   r   r   r   r   r   r   rn   r~   r   )r   metadatar   r;   r;   r?   r      s    


r   z/billing/webhooks/<provider>rc   c              
   C  s   t jdd}zAt jdd}t|tstd|  dkr+t|t j	dd t
|}nt| |t j	d	dt j	d
d |}t|  ||}W n. tyd } ztdt|ddfW  Y d}~S d}~w tyu   tddddf Y S w tddi|S )z3Receive provider-adapter events without a site JWT.T)cacheFrX   z%Webhook payload must be a JSON objectstripezStripe-Signaturery   zX-Billing-TimestampzX-Billing-Signaturer4   r5   r   NzInvalid billing webhookr6   r:   )r	   get_datark   rl   rm   r   lowerr   headersrn   r   r   r   r   rE   	Exception)rc   raw_bodyrv   platform_payloadresultrH   r;   r;   r?   billing_webhook   s.   

"r   z/billing/statusc               
   C  s   zt t} t| d W n9 ty( } ztdt|ddfW  Y d }~S d }~w tyD } ztdt|ddfW  Y d }~S d }~ww tdt dS )Nzplatform:billing:readr4   r5   r8   r9   r:   )r6   billing)r   r	   r   r   r   rE   rF   r   rG   rH   r;   r;   r?   billing_status  s   ""r   z"/integrations/<app_id>/credentialsr   c              
   C  s   z!t t}t|d t|j| std|  t j|j| d}W nJ ty> } zt	dt
|ddfW  Y d }~S d }~w tyZ } zt	dt
|ddfW  Y d }~S d }~w tyk   t	dddd	f Y S w t	d
| |dS )Nzplatform:integrations:read!Subscription does not allow app: )rC   r   r4   r5   r8   r9   "Credential vault is not configured  r:   )r6   r   credentials)r   r	   r   r   rC   rF   r,   list_secret_metadatar   r   rE   r*   )r   rG   r   rH   r;   r;   r?   integration_credentials_status"  s$   

""r   c           	   
   C  s  z[t t}t|d t|j| std|  tjddpi }|d}t|t	r1|r1t
|dkr5tdt }g }| D ]\}}|j|j| t|t||jd |t| q>W n tyx } ztd	t|d
dfW  Y d }~S d }~w ty } ztd	t|d
dfW  Y d }~S d }~w ttfy } ztd	t|d
dfW  Y d }~S d }~w ty } ztd	t|d
dfW  Y d }~S d }~w ty   td	dd
df Y S w td| t|ddS )Nplatform:integrations:writer   TrX   r      z>credentials must be a non-empty object with at most 20 entries)rC   r   secret_namesecret_valueactor_idr4   r5   r8   r9   r   r|   r   r   r:   F)r6   r   
configuredvalues_returned)r   r	   r   r   rC   rF   rk   rn   rl   rm   lenr   r,   items
put_secretrE   rs   appendr   r   r+   r   r*   r   )	r   rG   rv   r   managerr   r   r   rH   r;   r;   r?   replace_integration_credentials5  sT   

	""""r   z0/integrations/<app_id>/credentials/<secret_name>r   c              
   C  s   z"t t}t|d t|j| std|  t j|j| |d}W nJ ty? } zt	dt
|ddfW  Y d }~S d }~w ty[ } zt	dt
|ddfW  Y d }~S d }~w tyl   t	dddd	f Y S w t	d
|ddS )Nr   r   )rC   r   r   r4   r5   r8   r9   r   r   r:   F)r6   deletedr   )r   r	   r   r   rC   rF   r,   delete_secretr   r   rE   r*   )r   r   rG   r   rH   r;   r;   r?   delete_integration_credential]  s$   

""r   z	/packagesc               
     s   z?t t t d t )} | tttj	d
tjtj  } fdd|D }W d    n1 s9w   Y  W n9 ty\ } ztdt|ddfW  Y d }~S d }~w tyx } ztdt|ddfW  Y d }~S d }~ww td	|d
S )Nzplatform:packages:readr   c                   s"   g | ]}t  j|jrt|qS r;   )r   rC   r   _package_payloadr   rG   r;   r?   r@   {  s    z-wordpress_package_catalog.<locals>.<listcomp>r4   r5   r8   r9   r:   )r6   packages)r   r	   r   r-   r   r   r/   r   r6   r   r   r   ru   r   r   r   r   rE   rF   )r   r   r   rH   r;   r   r?   wordpress_package_catalogp  s2   


""r   z)/packages/<package_id>/<version>/download
package_idc                 C  sh  zUt t}t|d t ?}|tttj| ktj	|ktj
dtjd  }|d u r3tdt|j|js>td|j|j}}W d    n1 sOw   Y  W nU tyr } ztdt|ddfW  Y d }~S d }~w ty } ztdt|ddfW  Y d }~S d }~w ty } ztdt|dd	fW  Y d }~S d }~ww t|d
d|ddS )Nzplatform:packages:downloadr   zPackage release not foundz(Subscription does not allow this packager4   r5   r8   r9   r|   r   Tr   )r   r	   r   r-   r   r   r/   r   r   ru   r6   r   r   r   r   r   r   rC   r   rF   r   r   r   r   rE   r
   )r   ru   rG   r   r   r   r   rH   r;   r;   r?   download_wordpress_package  sB   


"""r   r/   c                 C  s   | j pi }i d| jd| jd| jd| jd| jd| jd| jd| jd	| j	d
|
d|
d|
ddd|
dg d|
dd| jd upQ| jdkd| jd| jp[g d| jd usg| jdkrjd S d| j d| j dS )Nr   r   ru   r6   r   r   r   r   r   compatibilitybridge	wordpressphp)r   r   r   r   plugin_filer   r   capabilitiesr   z!/api/v1/bridge_platform/packages//r   )compatibility_jsonr   r   ru   r6   r   r   r   r   r   rn   r   r   capabilities_json)r   r   r;   r;   r?   r     sP   
	


r   z/connectionc                  C  s  zt t} t| d W n9 ty( } ztdt|ddfW  Y d}~S d}~w tyD } ztdt|ddfW  Y d}~S d}~ww | t_| j	dkrt
jdd	rzt| j| j| jt| jd
 | jt| jd W n1 tttfy } ztdt|ddfW  Y d}~S d}~w ty   tddddf Y S w tddd	ttj | j| j| j| j| j| j	t| jt| jdtj tj!| jdddS )zDReturn safe request and identity metadata after full JWT validation.platform:connectr4   r5   r8   Nr9   bootstrap_fileREGISTER_BOOTSTRAP_SITESTaud)r_   rC   issueraudiencekey_idpublic_key_pemzControl plane unavailabler   r:   flask_server)rC   r_   rs   r   kid
key_sourcerD   scopesjti)methodpathra   )r6   serviceauthenticatedserver_timerG   r	   )"r   r	   r   r   r   rE   rF   r   rG   r  r   configrn   r   r_   rC   r   claimsr   r   r   r   r   r   nowr   utc	isoformatrs   listrD   r  r  r  r   r;   r;   r?   connection_test  sb   ""

"
r  z/sitec               
   C  s   zt t} t| d W n9 ty( } ztdt|ddfW  Y d }~S d }~w tyD } ztdt|ddfW  Y d }~S d }~ww t| j}|d u rWtddddfS td|d	S )
Nr   r4   r5   r8   r9   zSite is not registeredr|   r:   )r6   site)	r   r	   r   r   r   rE   rF   r   r_   )rG   rH   r  r;   r;   r?   site_status  s   ""
r  z/entitlementsc               
   C  s   zt t} t| d t| j}W nU ty- } ztdt|ddfW  Y d }~S d }~w tyI } ztdt|ddfW  Y d }~S d }~w t	ye } ztdt|ddfW  Y d }~S d }~ww td|dS )	Nzplatform:entitlements:readr4   r5   r8   r9   r|   r:   )r6   r   )
r   r	   r   r   rC   r   r   rE   rF   r   )rG   r   rH   r;   r;   r?   effective_entitlements  s   
"""r  z/usagec               
   C  s   zt t} t| d t| j}t| j |d< W n9 ty6 } ztdt	|ddfW  Y d }~S d }~w t
yR } ztdt	|ddfW  Y d }~S d }~ww td| j|dS )	Nzplatform:usage:read
storage_mbr4   r5   r8   r9   r:   )r6   rC   usage)r   r	   r   r   rC   r   r<   r   r   rE   rF   )rG   r  rH   r;   r;   r?   effective_usage  s   

""r  z/site/keys/rotatec               
   C  sj  z;t t} t| d tjddpi }t|dpd }t|dp$d }|r,|s0tdt| j	| j
||d W nq tyX } ztd	t|d
dfW  Y d }~S d }~w tyt } ztd	t|d
dfW  Y d }~S d }~w ty } ztd	t|d
dfW  Y d }~S d }~w ty } ztd	t|d
dfW  Y d }~S d }~ww td|ddS )Nzplatform:keys:rotateTrX   r   ry   
public_keyzkid and public_key are required)r_   current_key_id
new_key_idr   r4   r5   r8   r9   r|   r   r:   zSigning key rotatedr6   r   r7   )r   r	   r   rk   rE   rn   ro   r   r   r_   r   r   r   rF   r   )rG   rv   new_kidr  rH   r;   r;   r?   rotate_site_key$  s8   

""""r  z/site/keys/<key_id>/revoker   c              
   C  s  zt t}t|d t|j| |jd W nq ty1 } ztdt|ddfW  Y d }~S d }~w t	yM } ztdt|ddfW  Y d }~S d }~w t
yi } ztdt|ddfW  Y d }~S d }~w ty } ztdt|ddfW  Y d }~S d }~ww td	| d
dS )Nzplatform:keys:revoke)r_   r   r  r4   r5   r8   r9   r|   r   r:   zSigning key revokedr  )r   r	   r   r   r_   r   r   r   rE   rF   r   r   )r   rG   rH   r;   r;   r?   revoke_site_key?  s,   

""""r  )
rC   rE   r^   r~   r[   r   rD   r   r   r   )ru   rE   )r   r.   r   rm   )rc   rE   )r   rE   )r   rE   r   rE   )r   rE   ru   rE   )r   r/   r   rm   )r   rE   )b__doc__
__future__r   r   r   rq   flaskr   r   r   r   r	   r
   
sqlalchemyr   sqlalchemy.excr   bridge_platform.auth.jwt_authr   r   r   r   bridge_platform.sites.registryr   r   r   r   $bridge_platform.entitlements.servicer   bridge_platform.quotas.servicer   bridge_platform.storage.servicer    bridge_platform.billing.webhooksr   r   r   &bridge_platform.billing.stripe_adapterr   r   r   r   bridge_platform.apps.registryr   r    #bridge_platform.agents.tool_catalogr!   bridge_platform.agents.runtimer"   r#    bridge_platform.agents.providersr$   bridge_platform.agents.profilesr%   r&   r'   'bridge_platform.logging.platform_loggerr(   r)   "bridge_platform.secrets.encryptionr*   r+   'bridge_platform.secrets.secrets_managerr,   config.control_planer-   bridge_platform.tenants.modelsr.   r/   __name__r0   rt   rn   rI   rW   postrx   r   rp   r   r   r   r   r   r   putr   deleter   r   r   r   r  r  r  r  r  r  r;   r;   r;   r?   <module>   s     


2



'


6



