add payload codec with permissions and data compartments

This commit is contained in:
juancwu 2026-04-29 00:55:58 +00:00
commit 71483982ca
2 changed files with 291 additions and 0 deletions

47
codec.go Normal file
View file

@ -0,0 +1,47 @@
package ficha
import (
"encoding/json"
"time"
)
// payload is the internal structure that gets encrypted into a token.
// It has two compartments for consumer use:
//
// - Permissions: a flat list of string identifiers that ficha understands
// and provides check methods for (Has, HasAll, HasAny, etc.).
// Consumers choose any string convention they like (e.g. "orders:read",
// "admin", "team:42:write").
//
// - Data: a freeform JSON blob that ficha treats as opaque bytes.
// Consumers marshal/unmarshal it into their own types.
//
// The payload itself is unexported because consumers never construct one directly.
type payload struct {
ID string `json:"id"`
Iat int64 `json:"iat"`
Exp int64 `json:"exp"`
Permissions []string `json:"perms,omitempty"`
Data json.RawMessage `json:"data,omitempty"`
}
// encodePayload serializes a payload to bytes ready for encryption.
func encodePayload(p payload) ([]byte, error) {
return json.Marshal(p)
}
// decodePayload deserializes bytes (post-decryption) back into a payload.
func decodePayload(b []byte) (payload, error) {
var p payload
if err := json.Unmarshal(b, &p); err != nil {
return payload{}, err
}
return p, nil
}
// expired reports whether the payload's expiry has passed at the given time.
// Uses >= so a token expiring exactly at `now` is considered expired
// (the conservative choice).
func (p payload) expired(now time.Time) bool {
return now.Unix() >= p.Exp
}