refactor: rename SolaceScanScout to Solace and update related configurations

- Updated branding from "SolaceScanScout" to "Solace" across various files including deployment scripts, API responses, and documentation.
- Changed default base URL for Playwright tests and updated security headers to reflect the new branding.
- Enhanced README and API documentation to include new authentication endpoints and product access details.

This refactor aligns the project branding and improves clarity in the API documentation.
This commit is contained in:
defiQUG
2026-04-10 12:52:17 -07:00
parent 6eef6b07f6
commit 0972178cc5
160 changed files with 13274 additions and 1061 deletions

View File

@@ -1,8 +1,8 @@
openapi: 3.0.3
info:
title: SolaceScanScout API
title: SolaceScan API
description: |
Blockchain Explorer API for ChainID 138 with tiered access control.
SolaceScan public explorer API for Chain 138 with tiered access control.
## Authentication
@@ -31,6 +31,10 @@ servers:
tags:
- name: Health
description: Health check endpoints
- name: Auth
description: Wallet and user-session authentication endpoints
- name: Access
description: RPC product catalog, subscriptions, and API key lifecycle
- name: Blocks
description: Block-related endpoints
- name: Transactions
@@ -76,6 +80,542 @@ paths:
type: string
example: connected
/api/v1/auth/nonce:
post:
tags:
- Auth
summary: Generate wallet auth nonce
description: Creates a nonce challenge for wallet-signature authentication.
operationId: createWalletAuthNonce
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/WalletNonceRequest'
responses:
'200':
description: Nonce generated
content:
application/json:
schema:
$ref: '#/components/schemas/WalletNonceResponse'
'400':
$ref: '#/components/responses/BadRequest'
'503':
description: Wallet auth storage or database not available
/api/v1/auth/wallet:
post:
tags:
- Auth
summary: Authenticate with wallet signature
description: Exchanges an address, signature, and nonce for a JWT used by wallet-authenticated track endpoints.
operationId: authenticateWallet
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/WalletAuthRequest'
responses:
'200':
description: Wallet authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/WalletAuthResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'503':
description: Wallet auth storage or database not available
/api/v1/auth/register:
post:
tags:
- Auth
summary: Register an explorer access user
description: "Creates an email/password account for the `/access` console and returns a user session token."
operationId: registerAccessUser
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UserRegisterRequest'
responses:
'200':
description: User created and session issued
content:
application/json:
schema:
$ref: '#/components/schemas/UserSessionResponse'
'400':
$ref: '#/components/responses/BadRequest'
'503':
description: Database not available
/api/v1/auth/login:
post:
tags:
- Auth
summary: Log in to the explorer access console
description: "Authenticates an email/password user and returns a user session token for `/api/v1/access/*` endpoints."
operationId: loginAccessUser
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UserLoginRequest'
responses:
'200':
description: Session issued
content:
application/json:
schema:
$ref: '#/components/schemas/UserSessionResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'503':
description: Database not available
/api/v1/access/me:
get:
tags:
- Access
summary: Get current access-console user
description: Returns the signed-in user profile and any known product subscriptions.
operationId: getAccessMe
security:
- userSessionAuth: []
responses:
'200':
description: Current user and subscriptions
content:
application/json:
schema:
$ref: '#/components/schemas/AccessMeResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'503':
description: Database not available
/api/v1/access/products:
get:
tags:
- Access
summary: List available RPC access products
description: Returns the commercial and operational RPC products currently modeled by the explorer access layer.
operationId: listAccessProducts
responses:
'200':
description: Product catalog
content:
application/json:
schema:
$ref: '#/components/schemas/AccessProductsResponse'
/api/v1/access/subscriptions:
get:
tags:
- Access
summary: List subscriptions for the signed-in user
operationId: listAccessSubscriptions
security:
- userSessionAuth: []
responses:
'200':
description: Subscription list
content:
application/json:
schema:
$ref: '#/components/schemas/AccessSubscriptionsResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'503':
description: Database not available
/api/v1/access/admin/subscriptions:
get:
tags:
- Access
summary: List subscriptions for admin review
description: Returns pending or filtered subscriptions for users whose email is allowlisted in `ACCESS_ADMIN_EMAILS`.
operationId: listAccessAdminSubscriptions
security:
- userSessionAuth: []
parameters:
- name: status
in: query
required: false
schema:
type: string
enum: [pending, active, suspended, revoked]
responses:
'200':
description: Subscription list
content:
application/json:
schema:
$ref: '#/components/schemas/AccessSubscriptionsResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
description: Admin privileges required
'503':
description: Database not available
post:
tags:
- Access
summary: Approve, suspend, or revoke a subscription
operationId: updateAccessAdminSubscription
security:
- userSessionAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AdminSubscriptionActionRequest'
responses:
'200':
description: Subscription updated
content:
application/json:
schema:
$ref: '#/components/schemas/AccessSubscriptionResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
description: Admin privileges required
'503':
description: Database not available
post:
tags:
- Access
summary: Request or activate product access
description: |
Creates or updates a product subscription. Self-service products become `active` immediately.
Approval-gated products such as Core RPC are created in `pending` state.
operationId: createAccessSubscription
security:
- userSessionAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateSubscriptionRequest'
responses:
'200':
description: Subscription saved
content:
application/json:
schema:
$ref: '#/components/schemas/AccessSubscriptionResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'503':
description: Database not available
/api/v1/access/api-keys:
get:
tags:
- Access
summary: List API keys for the signed-in user
operationId: listAccessApiKeys
security:
- userSessionAuth: []
responses:
'200':
description: API key records
content:
application/json:
schema:
$ref: '#/components/schemas/AccessAPIKeysResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'503':
description: Database not available
post:
tags:
- Access
summary: Create an API key
description: |
Issues an API key for the chosen tier and product. If the product is approval-gated and not already active
for the user, this endpoint returns `subscription_required`.
operationId: createAccessApiKey
security:
- userSessionAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateAPIKeyRequest'
responses:
'200':
description: API key created
content:
application/json:
schema:
$ref: '#/components/schemas/CreateAPIKeyResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
description: Product access is pending approval or inactive
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: subscription_required
message: Product access is pending approval or inactive
'503':
description: Database not available
/api/v1/access/api-keys/{id}:
post:
tags:
- Access
summary: Revoke an API key
description: "Revokes the identified API key. `DELETE` is also accepted by the handler, but the current frontend uses `POST`."
operationId: revokeAccessApiKey
security:
- userSessionAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
responses:
'200':
description: API key revoked
content:
application/json:
schema:
$ref: '#/components/schemas/RevokeAPIKeyResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'503':
description: Database not available
delete:
tags:
- Access
summary: Revoke an API key
description: Alternate HTTP verb for API key revocation.
operationId: revokeAccessApiKeyDelete
security:
- userSessionAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
responses:
'200':
description: API key revoked
content:
application/json:
schema:
$ref: '#/components/schemas/RevokeAPIKeyResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'503':
description: Database not available
/api/v1/access/usage:
get:
tags:
- Access
summary: Get usage summary for the signed-in user
description: Returns aggregated per-product usage derived from issued API keys.
operationId: getAccessUsage
security:
- userSessionAuth: []
responses:
'200':
description: Usage summary
content:
application/json:
schema:
$ref: '#/components/schemas/AccessUsageResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'503':
description: Database not available
/api/v1/access/audit:
get:
tags:
- Access
summary: Get recent API activity for the signed-in user
description: Returns recent validated API-key usage log rows for the current user.
operationId: getAccessAudit
security:
- userSessionAuth: []
parameters:
- name: limit
in: query
required: false
schema:
type: integer
minimum: 1
maximum: 200
default: 20
responses:
'200':
description: Audit entries
content:
application/json:
schema:
$ref: '#/components/schemas/AccessAuditResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'503':
description: Database not available
/api/v1/access/admin/audit:
get:
tags:
- Access
summary: Get recent API activity across users for admin review
description: Returns recent validated API-key usage log rows for access admins, optionally filtered by product.
operationId: getAccessAdminAudit
security:
- userSessionAuth: []
parameters:
- name: limit
in: query
required: false
schema:
type: integer
minimum: 1
maximum: 500
default: 50
- name: product
in: query
required: false
schema:
type: string
responses:
'200':
description: Audit entries
content:
application/json:
schema:
$ref: '#/components/schemas/AccessAuditResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'503':
description: Database not available
/api/v1/access/internal/validate-key:
get:
tags:
- Access
summary: Validate an API key for nginx auth_request or similar edge subrequests
description: >-
Requires `X-Access-Internal-Secret` and accepts the presented API key in
`X-API-Key` or `Authorization: Bearer ...`. Returns `200` or `401` and
emits validation metadata in response headers.
operationId: validateAccessApiKeyInternalGet
parameters:
- name: X-Access-Internal-Secret
in: header
required: true
schema:
type: string
- name: X-API-Key
in: header
required: false
schema:
type: string
- name: Authorization
in: header
required: false
schema:
type: string
- name: X-Access-Method
in: header
required: false
schema:
type: string
- name: X-Access-Request-Count
in: header
required: false
schema:
type: integer
responses:
'200':
description: Key validated
headers:
X-Validated-Product:
schema:
type: string
X-Validated-Tier:
schema:
type: string
X-Validated-Scopes:
schema:
type: string
X-Quota-Remaining:
schema:
type: string
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'503':
description: Database not available
post:
tags:
- Access
summary: Validate an API key for internal edge enforcement
description: Requires `X-Access-Internal-Secret` and returns validated key metadata while incrementing usage counters.
operationId: validateAccessApiKeyInternal
parameters:
- name: X-Access-Internal-Secret
in: header
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/InternalValidateAPIKeyRequest'
responses:
'200':
description: Key validated
content:
application/json:
schema:
$ref: '#/components/schemas/InternalValidateAPIKeyResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'503':
description: Database not available
/api/v1/blocks:
get:
tags:
@@ -272,7 +812,7 @@ paths:
'400':
$ref: '#/components/responses/BadRequest'
'503':
description: `TOKEN_AGGREGATION_BASE_URL` not configured
description: "`TOKEN_AGGREGATION_BASE_URL` not configured"
/api/v1/mission-control/bridge/trace:
get:
@@ -317,7 +857,7 @@ paths:
properties:
script:
type: string
description: Path relative to `OPERATOR_SCRIPTS_ROOT`
description: "Path relative to `OPERATOR_SCRIPTS_ROOT`"
args:
type: array
items:
@@ -363,8 +903,413 @@ components:
scheme: bearer
bearerFormat: JWT
description: JWT token obtained from /api/v1/auth/wallet
userSessionAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: User session token obtained from /api/v1/auth/register or /api/v1/auth/login
schemas:
WalletNonceRequest:
type: object
required: [address]
properties:
address:
type: string
pattern: '^0x[a-fA-F0-9]{40}$'
WalletNonceResponse:
type: object
properties:
address:
type: string
nonce:
type: string
message:
type: string
WalletAuthRequest:
type: object
required: [address, signature, nonce]
properties:
address:
type: string
pattern: '^0x[a-fA-F0-9]{40}$'
signature:
type: string
nonce:
type: string
WalletAuthResponse:
type: object
properties:
token:
type: string
expires_at:
type: string
format: date-time
user:
type: object
additionalProperties: true
User:
type: object
properties:
id:
type: string
email:
type: string
format: email
username:
type: string
is_admin:
type: boolean
UserRegisterRequest:
type: object
required: [email, username, password]
properties:
email:
type: string
format: email
username:
type: string
password:
type: string
minLength: 8
UserLoginRequest:
type: object
required: [email, password]
properties:
email:
type: string
format: email
password:
type: string
UserSessionResponse:
type: object
properties:
user:
$ref: '#/components/schemas/User'
token:
type: string
expires_at:
type: string
format: date-time
AccessProduct:
type: object
properties:
slug:
type: string
name:
type: string
provider:
type: string
vmid:
type: integer
http_url:
type: string
ws_url:
type: string
default_tier:
type: string
requires_approval:
type: boolean
billing_model:
type: string
description:
type: string
use_cases:
type: array
items:
type: string
management_features:
type: array
items:
type: string
AccessProductsResponse:
type: object
properties:
products:
type: array
items:
$ref: '#/components/schemas/AccessProduct'
note:
type: string
AccessAPIKeyRecord:
type: object
properties:
id:
type: string
name:
type: string
tier:
type: string
productSlug:
type: string
scopes:
type: array
items:
type: string
monthlyQuota:
type: integer
requestsUsed:
type: integer
approved:
type: boolean
approvedAt:
type: string
format: date-time
nullable: true
rateLimitPerSecond:
type: integer
rateLimitPerMinute:
type: integer
lastUsedAt:
type: string
format: date-time
nullable: true
expiresAt:
type: string
format: date-time
nullable: true
revoked:
type: boolean
createdAt:
type: string
format: date-time
AccessSubscription:
type: object
properties:
id:
type: string
productSlug:
type: string
tier:
type: string
status:
type: string
enum: [active, pending, suspended, revoked]
monthlyQuota:
type: integer
requestsUsed:
type: integer
requiresApproval:
type: boolean
approvedAt:
type: string
format: date-time
nullable: true
approvedBy:
type: string
nullable: true
notes:
type: string
nullable: true
createdAt:
type: string
format: date-time
AccessUsageSummary:
type: object
properties:
product_slug:
type: string
active_keys:
type: integer
requests_used:
type: integer
monthly_quota:
type: integer
AccessMeResponse:
type: object
properties:
user:
$ref: '#/components/schemas/User'
subscriptions:
type: array
items:
$ref: '#/components/schemas/AccessSubscription'
AccessSubscriptionsResponse:
type: object
properties:
subscriptions:
type: array
items:
$ref: '#/components/schemas/AccessSubscription'
AccessSubscriptionResponse:
type: object
properties:
subscription:
$ref: '#/components/schemas/AccessSubscription'
AccessAPIKeysResponse:
type: object
properties:
api_keys:
type: array
items:
$ref: '#/components/schemas/AccessAPIKeyRecord'
CreateSubscriptionRequest:
type: object
required: [product_slug]
properties:
product_slug:
type: string
tier:
type: string
CreateAPIKeyRequest:
type: object
required: [name]
properties:
name:
type: string
tier:
type: string
product_slug:
type: string
expires_days:
type: integer
monthly_quota:
type: integer
scopes:
type: array
items:
type: string
AdminSubscriptionActionRequest:
type: object
required: [subscription_id, status]
properties:
subscription_id:
type: string
status:
type: string
enum: [active, suspended, revoked]
notes:
type: string
CreateAPIKeyResponse:
type: object
properties:
api_key:
type: string
description: Plaintext key is only returned at creation time.
record:
$ref: '#/components/schemas/AccessAPIKeyRecord'
RevokeAPIKeyResponse:
type: object
properties:
revoked:
type: boolean
api_key_id:
type: string
AccessUsageResponse:
type: object
properties:
usage:
type: array
items:
$ref: '#/components/schemas/AccessUsageSummary'
AccessAuditEntry:
type: object
properties:
id:
type: integer
apiKeyId:
type: string
keyName:
type: string
productSlug:
type: string
methodName:
type: string
requestCount:
type: integer
lastIp:
type: string
nullable: true
createdAt:
type: string
format: date-time
AccessAuditResponse:
type: object
properties:
entries:
type: array
items:
$ref: '#/components/schemas/AccessAuditEntry'
InternalValidatedAPIKey:
type: object
properties:
apiKeyId:
type: string
userId:
type: string
name:
type: string
tier:
type: string
productSlug:
type: string
scopes:
type: array
items:
type: string
monthlyQuota:
type: integer
requestsUsed:
type: integer
rateLimitPerSecond:
type: integer
rateLimitPerMinute:
type: integer
lastUsedAt:
type: string
format: date-time
nullable: true
expiresAt:
type: string
format: date-time
nullable: true
InternalValidateAPIKeyRequest:
type: object
required: [api_key]
properties:
api_key:
type: string
method_name:
type: string
request_count:
type: integer
last_ip:
type: string
InternalValidateAPIKeyResponse:
type: object
properties:
valid:
type: boolean
key:
$ref: '#/components/schemas/InternalValidatedAPIKey'
Block:
type: object
properties: