feat: establish Orbit models, migrations and development baseline

This commit is contained in:
2026-09-17 07:04:21 +08:00
commit 4f2935e36f
84 changed files with 4915 additions and 0 deletions

65
model/id.go Normal file
View File

@@ -0,0 +1,65 @@
// Package model 提供 Orbit 各模块共用且不绑定存储实现的基础类型。
// 服务端模型不直接作为公开 SDK 协议。
package model
import (
"crypto/rand"
"database/sql/driver"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
)
// ID 是 128 位随机标识,对外使用小写十六进制,MySQL 使用 BINARY(16)。
// 标识只用于定位资源,不能作为访问凭据。
type ID string
func NewID() (ID, error) {
var b [16]byte
if _, err := rand.Read(b[:]); err != nil {
return "", err
}
return ID(hex.EncodeToString(b[:])), nil
}
func (id ID) Validate() error {
if len(id) != 32 {
return errors.New("id must contain 32 lowercase hexadecimal characters")
}
for _, c := range id {
if !(c >= '0' && c <= '9' || c >= 'a' && c <= 'f') {
return errors.New("id must contain lowercase hexadecimal characters")
}
}
return nil
}
func (id ID) Value() (driver.Value, error) {
if err := id.Validate(); err != nil {
return nil, err
}
return hex.DecodeString(string(id))
}
func (id *ID) Scan(src any) error {
b, ok := src.([]byte)
if !ok || len(b) != 16 {
return fmt.Errorf("id: expected BINARY(16), got %T", src)
}
*id = ID(hex.EncodeToString(b))
return nil
}
func (id *ID) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
candidate := ID(s)
if err := candidate.Validate(); err != nil {
return err
}
*id = candidate
return nil
}