photoncloud-monorepo/creditservice/proto/creditservice.proto
centra d2149b6249 fix(lightningstor): Fix SigV4 canonicalization for AWS S3 auth
- Replace form_urlencoded with RFC 3986 compliant URI encoding
- Implement aws_uri_encode() matching AWS SigV4 spec exactly
- Unreserved chars (A-Z,a-z,0-9,-,_,.,~) not encoded
- All other chars percent-encoded with uppercase hex
- Preserve slashes in paths, encode in query params
- Normalize empty paths to '/' per AWS spec
- Fix test expectations (body hash, HMAC values)
- Add comprehensive SigV4 signature determinism test

This fixes the canonicalization mismatch that caused signature
validation failures in T047. Auth can now be enabled for production.

Refs: T058.S1
2025-12-12 06:23:46 +09:00

277 lines
7.4 KiB
Protocol Buffer

syntax = "proto3";
package creditservice.v1;
option go_package = "github.com/cloud/creditservice/proto/creditservice/v1;creditservicev1";
import "google/protobuf/timestamp.proto";
// ============================================================================
// CreditService - Credit/Quota Management
// ============================================================================
service CreditService {
// Wallet operations
rpc GetWallet(GetWalletRequest) returns (GetWalletResponse);
rpc CreateWallet(CreateWalletRequest) returns (CreateWalletResponse);
rpc TopUp(TopUpRequest) returns (TopUpResponse);
rpc GetTransactions(GetTransactionsRequest) returns (GetTransactionsResponse);
// Admission Control (called by resource services before creation)
rpc CheckQuota(CheckQuotaRequest) returns (CheckQuotaResponse);
rpc ReserveCredits(ReserveCreditsRequest) returns (ReserveCreditsResponse);
rpc CommitReservation(CommitReservationRequest) returns (CommitReservationResponse);
rpc ReleaseReservation(ReleaseReservationRequest) returns (ReleaseReservationResponse);
// Billing (internal, called by billing batch)
rpc ProcessBilling(ProcessBillingRequest) returns (ProcessBillingResponse);
// Quota management
rpc SetQuota(SetQuotaRequest) returns (SetQuotaResponse);
rpc GetQuota(GetQuotaRequest) returns (GetQuotaResponse);
rpc ListQuotas(ListQuotasRequest) returns (ListQuotasResponse);
}
// ============================================================================
// Core Types
// ============================================================================
// Wallet represents a project's credit account
message Wallet {
string project_id = 1;
string org_id = 2;
// Balance in smallest credit unit (e.g., 100 = 1.00 credits)
int64 balance = 3;
// Reserved credits (pending reservations)
int64 reserved = 4;
// Total credits ever deposited
int64 total_deposited = 5;
// Total credits consumed
int64 total_consumed = 6;
WalletStatus status = 7;
google.protobuf.Timestamp created_at = 8;
google.protobuf.Timestamp updated_at = 9;
}
enum WalletStatus {
WALLET_STATUS_UNSPECIFIED = 0;
WALLET_STATUS_ACTIVE = 1;
WALLET_STATUS_SUSPENDED = 2; // Insufficient balance
WALLET_STATUS_CLOSED = 3;
}
// Transaction represents a credit movement
message Transaction {
string id = 1;
string project_id = 2;
TransactionType type = 3;
int64 amount = 4;
int64 balance_after = 5;
string description = 6;
string resource_id = 7; // Optional: related resource
google.protobuf.Timestamp created_at = 8;
}
enum TransactionType {
TRANSACTION_TYPE_UNSPECIFIED = 0;
TRANSACTION_TYPE_TOP_UP = 1; // Credit addition
TRANSACTION_TYPE_RESERVATION = 2; // Temporary hold
TRANSACTION_TYPE_CHARGE = 3; // Actual consumption
TRANSACTION_TYPE_RELEASE = 4; // Reservation release
TRANSACTION_TYPE_REFUND = 5; // Credit return
TRANSACTION_TYPE_BILLING_CHARGE = 6; // Periodic billing
}
// Reservation represents a credit hold (2-phase commit)
message Reservation {
string id = 1;
string project_id = 2;
int64 amount = 3;
ReservationStatus status = 4;
string description = 5;
google.protobuf.Timestamp expires_at = 6;
google.protobuf.Timestamp created_at = 7;
}
enum ReservationStatus {
RESERVATION_STATUS_UNSPECIFIED = 0;
RESERVATION_STATUS_PENDING = 1;
RESERVATION_STATUS_COMMITTED = 2;
RESERVATION_STATUS_RELEASED = 3;
RESERVATION_STATUS_EXPIRED = 4;
}
// Quota represents resource limits per project
message Quota {
string project_id = 1;
ResourceType resource_type = 2;
int64 limit = 3;
int64 current_usage = 4;
}
enum ResourceType {
RESOURCE_TYPE_UNSPECIFIED = 0;
RESOURCE_TYPE_VM_INSTANCE = 1;
RESOURCE_TYPE_VM_CPU = 2;
RESOURCE_TYPE_VM_MEMORY_GB = 3;
RESOURCE_TYPE_STORAGE_GB = 4;
RESOURCE_TYPE_NETWORK_PORT = 5;
RESOURCE_TYPE_LOAD_BALANCER = 6;
RESOURCE_TYPE_DNS_ZONE = 7;
RESOURCE_TYPE_DNS_RECORD = 8;
RESOURCE_TYPE_K8S_CLUSTER = 9;
RESOURCE_TYPE_K8S_NODE = 10;
}
// ============================================================================
// Wallet Operations
// ============================================================================
message GetWalletRequest {
string project_id = 1;
}
message GetWalletResponse {
Wallet wallet = 1;
}
message CreateWalletRequest {
string project_id = 1;
string org_id = 2;
int64 initial_balance = 3; // Optional initial credit
}
message CreateWalletResponse {
Wallet wallet = 1;
}
message TopUpRequest {
string project_id = 1;
int64 amount = 2;
string description = 3; // e.g., "Payment ID: xxx"
}
message TopUpResponse {
Wallet wallet = 1;
Transaction transaction = 2;
}
message GetTransactionsRequest {
string project_id = 1;
// Pagination
int32 page_size = 2;
string page_token = 3;
// Filters
TransactionType type_filter = 4;
google.protobuf.Timestamp start_time = 5;
google.protobuf.Timestamp end_time = 6;
}
message GetTransactionsResponse {
repeated Transaction transactions = 1;
string next_page_token = 2;
}
// ============================================================================
// Admission Control
// ============================================================================
message CheckQuotaRequest {
string project_id = 1;
ResourceType resource_type = 2;
int32 quantity = 3;
int64 estimated_cost = 4; // Optional: estimated credit cost
}
message CheckQuotaResponse {
bool allowed = 1;
string reason = 2; // Reason if not allowed
int64 available_balance = 3;
int64 available_quota = 4;
}
message ReserveCreditsRequest {
string project_id = 1;
int64 amount = 2;
string description = 3;
string resource_type = 4; // For tracking
int32 ttl_seconds = 5; // Reservation TTL (default: 300)
}
message ReserveCreditsResponse {
Reservation reservation = 1;
}
message CommitReservationRequest {
string reservation_id = 1;
int64 actual_amount = 2; // May differ from reserved amount
string resource_id = 3; // Created resource ID for tracking
}
message CommitReservationResponse {
Transaction transaction = 1;
Wallet wallet = 2;
}
message ReleaseReservationRequest {
string reservation_id = 1;
string reason = 2; // Why released (e.g., "creation failed")
}
message ReleaseReservationResponse {
bool success = 1;
}
// ============================================================================
// Billing
// ============================================================================
message ProcessBillingRequest {
string project_id = 1; // Empty = process all projects
google.protobuf.Timestamp billing_period_start = 2;
google.protobuf.Timestamp billing_period_end = 3;
}
message ProcessBillingResponse {
int32 projects_processed = 1;
int64 total_charged = 2;
repeated BillingResult results = 3;
}
message BillingResult {
string project_id = 1;
int64 amount_charged = 2;
bool success = 3;
string error = 4;
}
// ============================================================================
// Quota Management
// ============================================================================
message SetQuotaRequest {
string project_id = 1;
ResourceType resource_type = 2;
int64 limit = 3;
}
message SetQuotaResponse {
Quota quota = 1;
}
message GetQuotaRequest {
string project_id = 1;
ResourceType resource_type = 2;
}
message GetQuotaResponse {
Quota quota = 1;
}
message ListQuotasRequest {
string project_id = 1;
}
message ListQuotasResponse {
repeated Quota quotas = 1;
}