feat: add marketplace metrics, privacy features, and service registry endpoints

- Add Prometheus metrics for marketplace API throughput and error rates with new dashboard panels
- Implement confidential transaction models with encryption support and access control
- Add key management system with registration, rotation, and audit logging
- Create services and registry routers for service discovery and management
- Integrate ZK proof generation for privacy-preserving receipts
- Add metrics instru
This commit is contained in:
oib
2025-12-22 10:33:23 +01:00
parent d98b2c7772
commit c8be9d7414
260 changed files with 59033 additions and 351 deletions

View File

@ -0,0 +1,304 @@
# AITBC Extension Manifest
# This file defines the extension metadata and lifecycle configuration
apiVersion: "v1"
kind: "Extension"
# Basic information
metadata:
name: "{{ cookiecutter.extension_name }}"
displayName: "{{ cookiecutter.extension_display_name }}"
description: "{{ cookiecutter.extension_description }}"
version: "{{ cookiecutter.version }}"
author: "{{ cookiecutter.author_name }}"
email: "{{ cookiecutter.author_email }}"
license: "{{ cookiecutter.license }}"
homepage: "https://github.com/{{ cookiecutter.github_username }}/{{ cookiecutter.extension_name }}"
repository: "https://github.com/{{ cookiecutter.github_username }}/{{ cookiecutter.extension_name }}.git"
documentation: "https://{{ cookiecutter.extension_name }}.readthedocs.io"
# Extension classification
spec:
type: "{{ cookiecutter.extension_type }}"
category:
{% if cookiecutter.extension_type == "payment" %}
- "payment-processor"
{% elif cookiecutter.extension_type == "erp" %}
- "erp-connector"
{% elif cookiecutter.extension_type == "analytics" %}
- "analytics-tool"
{% else %}
- "developer-tool"
{% endif %}
# AITBC compatibility
aitbc:
minVersion: "1.0.0"
maxVersion: "2.0.0"
sdkVersion: "^1.0.0"
# Runtime requirements
runtime:
python: ">= {{ cookiecutter.python_version }}"
{% if cookiecutter.use_asyncio %}
features: ["async"]
{% endif %}
# Dependencies
dependencies:
core:
- "aitbc-enterprise>=1.0.0"
{% if cookiecutter.extension_type == "payment" %}
payments:
- "stripe>=5.0.0"
{% elif cookiecutter.extension_type == "erp" %}
erp:
- "requests>=2.25.0"
- "pandas>=1.3.0"
{% elif cookiecutter.extension_type == "analytics" %}
analytics:
- "matplotlib>=3.5.0"
- "plotly>=5.0.0"
{% else %}
devtools:
- "click>=8.0.0"
{% endif %}
# Extension configuration schema
configSchema:
type: "object"
properties:
{% if cookiecutter.extension_type == "payment" %}
api_key:
type: "string"
description: "API key for the payment service"
sensitive: true
webhook_secret:
type: "string"
description: "Webhook secret for verification"
sensitive: true
sandbox:
type: "boolean"
description: "Use sandbox environment"
default: false
{% elif cookiecutter.extension_type == "erp" %}
host:
type: "string"
description: "ERP system host"
format: "hostname"
port:
type: "integer"
description: "ERP system port"
default: 443
username:
type: "string"
description: "ERP username"
sensitive: true
password:
type: "string"
description: "ERP password"
sensitive: true
database:
type: "string"
description: "ERP database name"
{% elif cookiecutter.extension_type == "analytics" %}
data_source:
type: "string"
description: "Data source URL"
refresh_interval:
type: "integer"
description: "Data refresh interval in seconds"
default: 300
retention_days:
type: "integer"
description: "Data retention period in days"
default: 90
{% else %}
debug_mode:
type: "boolean"
description: "Enable debug logging"
default: false
log_level:
type: "string"
enum: ["DEBUG", "INFO", "WARNING", "ERROR"]
default: "INFO"
{% endif %}
required:
{% if cookiecutter.extension_type == "payment" %}
- "api_key"
{% elif cookiecutter.extension_type == "erp" %}
- "host"
- "username"
- "password"
- "database"
{% elif cookiecutter.extension_type == "analytics" %}
- "data_source"
{% endif %}
# Health check configuration
health:
enabled: true
endpoint: "/health"
interval: 30
timeout: 5
checks:
- name: "service_connection"
type: "external"
command: "python -c 'import {{ cookiecutter.package_name }}; print(\"OK\")'"
{% if cookiecutter.extension_type == "payment" %}
- name: "payment_api"
type: "http"
url: "https://api.stripe.com/v1"
expectedStatus: 200
{% endif %}
# Metrics configuration
metrics:
enabled: true
endpoint: "/metrics"
format: "prometheus"
customMetrics:
{% if cookiecutter.extension_type == "payment" %}
- name: "payment_operations_total"
type: "counter"
help: "Total number of payment operations"
- name: "payment_amount_sum"
type: "histogram"
help: "Payment amount distribution"
{% elif cookiecutter.extension_type == "erp" %}
- name: "sync_operations_total"
type: "counter"
help: "Total number of sync operations"
- name: "sync_records_processed"
type: "counter"
help: "Total records processed during sync"
{% elif cookiecutter.extension_type == "analytics" %}
- name: "analytics_queries_total"
type: "counter"
help: "Total number of analytics queries"
- name: "data_processing_time"
type: "histogram"
help: "Time spent processing analytics data"
{% endif %}
# Webhook configuration (if applicable)
{% if cookiecutter.extension_type == "payment" %}
webhooks:
enabled: true
events:
- "payment.created"
- "payment.succeeded"
- "payment.failed"
- "refund.created"
endpoint: "/webhooks"
secret: "{{ cookiecutter.extension_name }}_webhook"
retryPolicy:
maxRetries: 3
backoff: "exponential"
{% endif %}
# Security configuration
security:
{% if cookiecutter.extension_type == "payment" %}
pciCompliance: true
dataEncryption: true
{% elif cookiecutter.extension_type == "erp" %}
tlsRequired: true
auditLogging: true
{% endif %}
permissions:
- "read:transactions"
- "write:transactions"
{% if cookiecutter.extension_type == "erp" %}
- "read:customers"
- "write:customers"
{% endif %}
# Deployment configuration
deployment:
type: "docker"
# Docker configuration
docker:
image: "{{ cookiecutter.github_username }}/{{ cookiecutter.extension_name }}:{{ cookiecutter.version }}"
ports:
- "8080:8080"
environment:
- "AITBC_ENV=production"
- "LOG_LEVEL=INFO"
volumes:
- "/data/{{ cookiecutter.extension_name }}:/app/data"
resources:
limits:
cpu: "500m"
memory: "512Mi"
requests:
cpu: "100m"
memory: "128Mi"
# Kubernetes configuration (optional)
kubernetes:
enabled: false
replicas: 2
service:
type: "ClusterIP"
port: 80
ingress:
enabled: false
host: "{{ cookiecutter.extension_name }}.aitbc.local"
# Scaling configuration
scaling:
minReplicas: 1
maxReplicas: 10
targetCPUUtilization: 70
targetMemoryUtilization: 80
# Testing configuration
testing:
frameworks:
- "pytest"
- "pytest-asyncio" # if asyncio enabled
coverage:
enabled: true
threshold: 80
environments:
- name: "unit"
command: "pytest tests/unit/"
- name: "integration"
command: "pytest tests/integration/"
- name: "e2e"
command: "pytest tests/e2e/"
# Documentation
documentation:
type: "sphinx"
theme: "sphinx_rtd_theme"
build:
command: "sphinx-build -b html docs docs/_build"
deploy:
type: "github-pages"
branch: "gh-pages"
# Release configuration
release:
type: "semantic"
branches:
main: "main"
develop: "develop"
release: "release/*"
changelog:
enabled: true
file: "CHANGELOG.md"
artifacts:
- "dist/*.whl"
- "dist/*.tar.gz"
# Support information
support:
website: "https://{{ cookiecutter.extension_name }}.aitbc.io"
documentation: "https://{{ cookiecutter.extension_name }}.readthedocs.io"
issues: "https://github.com/{{ cookiecutter.github_username }}/{{ cookiecutter.extension_name }}/issues"
discussions: "https://github.com/{{ cookiecutter.github_username }}/{{ cookiecutter.extension_name }}/discussions"
email: "{{ cookiecutter.author_email }}"
slack: "#{{ cookiecutter.extension_name }}-support"

View File

@ -0,0 +1,97 @@
"""
Setup script for {{ cookiecutter.extension_display_name }}
"""
from setuptools import setup, find_packages
import os
# Read the contents of README file
this_directory = os.path.abspath(os.path.dirname(__file__))
with open(os.path.join(this_directory, 'README.md'), encoding='utf-8') as f:
long_description = f.read()
# Read requirements
with open(os.path.join(this_directory, 'requirements.txt'), encoding='utf-8') as f:
requirements = f.read().splitlines()
setup(
name="{{ cookiecutter.package_name }}",
version="{{ cookiecutter.version }}",
author="{{ cookiecutter.author_name }}",
author_email="{{ cookiecutter.author_email }}",
description="{{ cookiecutter.extension_description }}",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/{{ cookiecutter.github_username }}/{{ cookiecutter.extension_name }}",
packages=find_packages(),
classifiers=[
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: {{ cookiecutter.license }} License",
"Operating System :: OS Independent",
"Programming Language :: Python :: {{ cookiecutter.python_version }}",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Office/Business :: Financial",
{% if cookiecutter.extension_type == "payment" %}
"Topic :: Office/Business :: Financial :: Point-Of-Sale",
{% elif cookiecutter.extension_type == "erp" %}
"Topic :: Office/Business",
{% elif cookiecutter.extension_type == "analytics" %}
"Topic :: Scientific/Engineering :: Information Analysis",
{% else %}
"Topic :: Software Development :: Libraries",
{% endif %}
],
python_requires=">={{ cookiecutter.python_version }}",
install_requires=requirements,
extras_require={
"dev": [
"pytest>=6.0",
"pytest-asyncio>=0.18.0" if {{ cookiecutter.use_asyncio|lower }} else "",
"pytest-cov>=2.12",
"black>=21.0",
"isort>=5.9",
"flake8>=3.9",
"mypy>=0.910",
"pre-commit>=2.15",
],
"docs": [
"sphinx>=4.0",
"sphinx-rtd-theme>=1.0",
"myst-parser>=0.15",
],
{% if cookiecutter.extension_type == "analytics" %}
"viz": [
"matplotlib>=3.5.0",
"plotly>=5.0.0",
"seaborn>=0.11.0",
],
{% endif %}
},
entry_points={
"console_scripts": [
"{{ cookiecutter.package_name }}={{ cookiecutter.package_name }}.cli:main",
],
"aitbc.extensions": [
"{{ cookiecutter.extension_name }}={{ cookiecutter.package_name }}.{{ cookiecutter.class_name }}",
],
},
include_package_data=True,
package_data={
"{{ cookiecutter.package_name }}": [
"templates/*.yaml",
"templates/*.json",
"static/*",
],
},
zip_safe=False,
keywords="aitbc {{ cookiecutter.extension_type }} {{ cookiecutter.extension_name }}",
project_urls={
"Bug Reports": "https://github.com/{{ cookiecutter.github_username }}/{{ cookiecutter.extension_name }}/issues",
"Source": "https://github.com/{{ cookiecutter.github_username }}/{{ cookiecutter.extension_name }}",
"Documentation": "https://{{ cookiecutter.extension_name }}.readthedocs.io",
},
)

View File

@ -0,0 +1,13 @@
"""
{{ cookiecutter.extension_display_name }} - AITBC Extension
{{ cookiecutter.extension_description }}
"""
__version__ = "{{ cookiecutter.version }}"
__author__ = "{{ cookiecutter.author_name }} <{{ cookiecutter.author_email }}>"
__license__ = "{{ cookiecutter.license }}"
from .{{ cookiecutter.extension_name }} import {{ cookiecutter.class_name }}
__all__ = ["{{ cookiecutter.class_name }}"]

View File

@ -0,0 +1,369 @@
"""
{{ cookiecutter.extension_display_name }} Connector
{{ cookiecutter.extension_description }}
"""
{% if cookiecutter.use_asyncio %}
import asyncio
from typing import Dict, Any, Optional, List
{% else %}
from typing import Dict, Any, Optional, List
{% endif %}
from aitbc_enterprise.base import BaseConnector
from aitbc_enterprise.core import AITBCClient, ConnectorConfig
from aitbc_enterprise.exceptions import ConnectorError
{% if cookiecutter.extension_type == "payment" %}
from aitbc_enterprise.payments.base import PaymentConnector, Charge, Refund, PaymentMethod
{% elif cookiecutter.extension_type == "erp" %}
from aitbc_enterprise.erp.base import ERPConnector, ERPDataModel, SyncResult
{% endif %}
class {{ cookiecutter.class_name }}({% if cookiecutter.extension_type == "payment" %}PaymentConnector{% elif cookiecutter.extension_type == "erp" %}ERPConnector{% else %}BaseConnector{% endif %}):
"""
{{ cookiecutter.extension_display_name }} connector for AITBC
This connector provides integration with {{ cookiecutter.extension_name }}.
"""
def __init__(self, client: AITBCClient, config: ConnectorConfig):
"""
Initialize the {{ cookiecutter.extension_name }} connector
Args:
client: AITBC client instance
config: Connector configuration
"""
super().__init__(client, config)
# Initialize your service client here
# Example:
# self.service_client = ServiceClient(
# api_key=config.settings.get("api_key"),
# base_url=config.settings.get("base_url")
# )
self.logger = __import__('logging').getLogger(f"aitbc.{self.__class__.__name__}")
{% if cookiecutter.use_asyncio %}
async def initialize(self):
"""
Initialize the connector and establish connections
"""
await super().initialize()
# Initialize your service connection here
# Example:
# await self.service_client.authenticate()
self.logger.info("{{ cookiecutter.class_name }} initialized successfully")
async def cleanup(self):
"""
Cleanup resources and close connections
"""
# Cleanup your service connection here
# Example:
# await self.service_client.close()
await super().cleanup()
self.logger.info("{{ cookiecutter.class_name }} cleaned up successfully")
{% endif %}
{% if cookiecutter.extension_type == "payment" %}
{% if cookiecutter.use_asyncio %}
async def create_charge(
self,
amount: int,
currency: str,
source: str,
description: Optional[str] = None,
metadata: Optional[Dict[str, Any]] = None
) -> Charge:
"""
Create a payment charge
Args:
amount: Amount in smallest currency unit
currency: Currency code (e.g., 'USD')
source: Payment source identifier
description: Optional description
metadata: Optional metadata
Returns:
Charge object representing the payment
"""
try:
# Implement charge creation logic here
# Example:
# charge_data = await self.service_client.create_charge({
# "amount": amount,
# "currency": currency,
# "source": source,
# "description": description,
# "metadata": metadata or {}
# })
# Convert to AITBC Charge format
charge = Charge(
id="charge_123", # From service response
amount=amount,
currency=currency,
status="pending", # From service response
created_at=__import__('datetime').datetime.utcnow(),
metadata=metadata or {}
)
# Log the operation
await self._log_operation("create_charge", {
"amount": amount,
"currency": currency,
"charge_id": charge.id
})
return charge
except Exception as e:
self.logger.error(f"Failed to create charge: {e}")
raise ConnectorError(f"Charge creation failed: {e}")
async def refund_charge(
self,
charge_id: str,
amount: Optional[int] = None,
reason: Optional[str] = None
) -> Refund:
"""
Refund a charge
Args:
charge_id: ID of charge to refund
amount: Optional amount to refund (full if None)
reason: Optional refund reason
Returns:
Refund object
"""
# Implement refund logic here
pass
async def get_charge(self, charge_id: str) -> Charge:
"""
Get charge details
Args:
charge_id: Charge ID
Returns:
Charge object
"""
# Implement charge retrieval here
pass
{% else %}
def create_charge(
self,
amount: int,
currency: str,
source: str,
description: Optional[str] = None,
metadata: Optional[Dict[str, Any]] = None
) -> Charge:
"""
Create a payment charge (synchronous version)
"""
# Synchronous implementation
pass
{% endif %}
{% elif cookiecutter.extension_type == "erp" %}
{% if cookiecutter.use_asyncio %}
async def sync_data(
self,
data_type: str,
start_date: Optional[__import__('datetime').datetime] = None,
end_date: Optional[__import__('datetime').datetime] = None
) -> SyncResult:
"""
Sync data from ERP system
Args:
data_type: Type of data to sync (e.g., 'customers', 'orders')
start_date: Optional start date for sync
end_date: Optional end date for sync
Returns:
SyncResult with sync statistics
"""
try:
# Implement sync logic here
# Example:
# data = await self.service_client.get_data(
# data_type=data_type,
# start_date=start_date,
# end_date=end_date
# )
# Process and transform data
# processed_data = self._transform_data(data)
# Store in AITBC
# await self._store_data(processed_data)
result = SyncResult(
records_processed=100, # From actual sync
records_created=80,
records_updated=20,
errors=[],
sync_time=__import__('datetime').datetime.utcnow()
)
# Log the operation
await self._log_operation("sync_data", {
"data_type": data_type,
"records_processed": result.records_processed
})
return result
except Exception as e:
self.logger.error(f"Failed to sync {data_type}: {e}")
raise ConnectorError(f"Data sync failed: {e}")
async def get_data_model(self, data_type: str) -> ERPDataModel:
"""
Get data model for ERP data type
Args:
data_type: Type of data
Returns:
ERPDataModel definition
"""
# Implement data model retrieval here
pass
{% else %}
def sync_data(
self,
data_type: str,
start_date: Optional[__import__('datetime').datetime] = None,
end_date: Optional[__import__('datetime').datetime] = None
) -> SyncResult:
"""
Sync data from ERP system (synchronous version)
"""
# Synchronous implementation
pass
{% endif %}
{% else %}
{% if cookiecutter.use_asyncio %}
async def execute_operation(
self,
operation: str,
parameters: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
"""
Execute a custom operation
Args:
operation: Operation name
parameters: Optional parameters
Returns:
Operation result
"""
try:
# Implement your custom operation here
result = {
"operation": operation,
"parameters": parameters,
"result": "success",
"timestamp": __import__('datetime').datetime.utcnow().isoformat()
}
# Log the operation
await self._log_operation("execute_operation", {
"operation": operation,
"parameters": parameters
})
return result
except Exception as e:
self.logger.error(f"Failed to execute {operation}: {e}")
raise ConnectorError(f"Operation failed: {e}")
{% else %}
def execute_operation(
self,
operation: str,
parameters: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
"""
Execute a custom operation (synchronous version)
"""
# Synchronous implementation
pass
{% endif %}
{% endif %}
# Helper methods
def _transform_data(self, data: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
"""
Transform data from external format to AITBC format
Args:
data: Raw data from external service
Returns:
Transformed data
"""
# Implement data transformation logic here
return data
{% if cookiecutter.use_asyncio %}
async def _store_data(self, data: List[Dict[str, Any]]) -> bool:
"""
Store data in AITBC
Args:
data: Data to store
Returns:
True if successful
"""
# Implement data storage logic here
return True
{% else %}
def _store_data(self, data: List[Dict[str, Any]]) -> bool:
"""
Store data in AITBC (synchronous version)
"""
# Synchronous implementation
return True
{% endif %}
def validate_config(self) -> bool:
"""
Validate connector configuration
Returns:
True if configuration is valid
"""
required_settings = []
{% if cookiecutter.extension_type == "payment" %}
required_settings = ["api_key", "webhook_secret"]
{% elif cookiecutter.extension_type == "erp" %}
required_settings = ["host", "username", "password", "database"]
{% endif %}
for setting in required_settings:
if setting not in self.config.settings:
raise ConnectorError(f"Missing required setting: {setting}")
return True