cleaned up wire representation of components

Signed-off-by: Dmitri Dolguikh <dmitri.external@netbird.io>
This commit is contained in:
Dmitri Dolguikh
2026-07-08 21:29:14 +02:00
parent 7c7dfd7f1d
commit a36a1a3c26
15 changed files with 524 additions and 542 deletions

View File

@@ -55,7 +55,7 @@ type NameServerGroup struct {
AccountID string `gorm:"index"`
// AccountSeqID is a per-account monotonically increasing identifier used as the
// compact wire id when sending NetworkMap components to capable peers.
AccountSeqID uint32 `json:"-" gorm:"index:idx_nameserver_groups_account_seq_id;not null;default:0"`
AccountSeqID int32 `json:"-" gorm:"not null;default:0"`
// Name group name
Name string
// Description group description

View File

@@ -88,7 +88,7 @@ func EncodeNetworkMapEnvelope(in ComponentsEnvelopeInput) *proto.NetworkMapEnvel
// policies + resource-only policies) so encodeResourcePoliciesMap can
// translate every *Policy pointer to a wire index.
allPolicies := unionPolicies(c.Policies, c.ResourcePoliciesMap)
policies, policyToIdxs := enc.encodePolicies(allPolicies)
policies := enc.encodePolicies(allPolicies)
// Phase 3: emit. Order of struct field expressions no longer matters:
// every encoder either reads from the dedup tables or works on
@@ -115,7 +115,7 @@ func EncodeNetworkMapEnvelope(in ComponentsEnvelopeInput) *proto.NetworkMapEnvel
AccountZones: encodeCustomZones(c.AccountZones),
NetworkResources: enc.encodeNetworkResources(c.NetworkResources),
RoutersMap: enc.encodeRoutersMap(c.RoutersMap),
ResourcePoliciesMap: enc.encodeResourcePoliciesMap(c.ResourcePoliciesMap, policyToIdxs),
ResourcePoliciesMap: enc.encodeResourcePoliciesMap(c.ResourcePoliciesMap),
GroupIdToUserIds: enc.encodeGroupIDToUserIDs(c.GroupIDToUserIDs),
AllowedUserIds: stringSetToSlice(c.AllowedUserIDs),
PostureFailedPeers: enc.encodePostureFailedPeers(c.PostureFailedPeers),
@@ -170,7 +170,7 @@ func (e *componentEncoder) appendPeer(p *nbpeer.Peer) uint32 {
}
idx := uint32(len(e.peers))
e.peerOrder[p.ID] = idx
e.peers = append(e.peers, toPeerCompact(p, e.agentVersionIndex(p.Meta.WtVersion)))
e.peers = append(e.peers, toPeerCompact(p))
return idx
}
@@ -246,13 +246,12 @@ func (e *componentEncoder) encodeGroups() []*proto.GroupCompact {
// list and a map from policy pointer to the indexes of its emitted rules in
// that list — used by encodeResourcePoliciesMap to translate
// ResourcePoliciesMap[resourceID][]*Policy into wire-side indexes.
func (e *componentEncoder) encodePolicies(policies []*types.Policy) ([]*proto.PolicyCompact, map[*types.Policy][]uint32) {
func (e *componentEncoder) encodePolicies(policies []*types.Policy) []*proto.PolicyCompact {
if len(policies) == 0 {
return nil, nil
return nil
}
out := make([]*proto.PolicyCompact, 0, len(policies))
idxByPolicy := make(map[*types.Policy][]uint32, len(policies))
for _, pol := range policies {
if !pol.HasSeqID() || !pol.Enabled {
@@ -262,11 +261,10 @@ func (e *componentEncoder) encodePolicies(policies []*types.Policy) ([]*proto.Po
if r == nil || !r.Enabled {
continue
}
idxByPolicy[pol] = append(idxByPolicy[pol], uint32(len(out)))
out = append(out, e.encodePolicyRule(pol, r))
}
}
return out, idxByPolicy
return out
}
// encodePolicyRule maps a single PolicyRule under pol to a PolicyCompact entry.
@@ -290,11 +288,11 @@ func (e *componentEncoder) encodePolicyRule(pol *types.Policy, r *types.PolicyRu
// groupSeqIDs maps the xid group IDs in src to their per-account seq ids,
// dropping any group that has no seq id assigned.
func (e *componentEncoder) groupSeqIDs(src []string) []uint32 {
func (e *componentEncoder) groupSeqIDs(src []string) []int32 {
if len(src) == 0 {
return nil
}
out := make([]uint32, 0, len(src))
out := make([]int32, 0, len(src))
for _, gid := range src {
if seq, ok := e.groupSeq(gid); ok {
out = append(out, seq)
@@ -346,11 +344,11 @@ func unionPolicies(policies []*types.Policy, resourcePolicies map[string][]*type
// group xid → local-user names) to the wire form (map keyed by group
// account_seq_id → UserNameList). Groups without a seq id are dropped —
// matches how source/destination group references handle the same case.
func (e *componentEncoder) encodeAuthorizedGroups(m map[string][]string) map[uint32]*proto.UserNameList {
func (e *componentEncoder) encodeAuthorizedGroups(m map[string][]string) map[int32]*proto.UserNameList {
if len(m) == 0 {
return nil
}
out := make(map[uint32]*proto.UserNameList, len(m))
out := make(map[int32]*proto.UserNameList, len(m))
for groupID, names := range m {
seq, ok := e.groupSeq(groupID)
if !ok {
@@ -361,7 +359,7 @@ func (e *componentEncoder) encodeAuthorizedGroups(m map[string][]string) map[uin
return out
}
func (e *componentEncoder) groupSeq(groupID string) (uint32, bool) {
func (e *componentEncoder) groupSeq(groupID string) (int32, bool) {
g, ok := e.components.Groups[groupID]
if !ok || !g.HasSeqID() {
return 0, false
@@ -392,11 +390,11 @@ func (e *componentEncoder) resourceToProto(r types.Resource) *proto.ResourceComp
// per-account integer ids using the NetworkMapComponents.PostureCheckXIDToSeq
// lookup. Unresolvable xids are silently dropped — matches how group/peer
// references handle the same case.
func (e *componentEncoder) postureCheckSeqs(xids []string) []uint32 {
func (e *componentEncoder) postureCheckSeqs(xids []string) []int32 {
if len(xids) == 0 || len(e.components.PostureCheckXIDToSeq) == 0 {
return nil
}
out := make([]uint32, 0, len(xids))
out := make([]int32, 0, len(xids))
for _, xid := range xids {
if seq, ok := e.components.PostureCheckXIDToSeq[xid]; ok {
out = append(out, seq)
@@ -408,7 +406,7 @@ func (e *componentEncoder) postureCheckSeqs(xids []string) []uint32 {
// networkSeq translates a Network xid to its per-account integer id using
// the NetworkMapComponents.NetworkXIDToSeq lookup. Returns (0,false) when
// the xid isn't known — callers decide whether to skip the parent record.
func (e *componentEncoder) networkSeq(xid string) (uint32, bool) {
func (e *componentEncoder) networkSeq(xid string) (int32, bool) {
if xid == "" {
return 0, false
}
@@ -424,7 +422,7 @@ func (e *componentEncoder) encodeDNSSettings(s *types.DNSSettings) *proto.DNSSet
return nil
}
out := &proto.DNSSettingsCompact{
DisabledManagementGroupIds: make([]uint32, 0, len(s.DisabledManagementGroups)),
DisabledManagementGroupIds: make([]int32, 0, len(s.DisabledManagementGroups)),
}
for _, gid := range s.DisabledManagementGroups {
if seq, ok := e.groupSeq(gid); ok {
@@ -472,11 +470,11 @@ func (e *componentEncoder) encodeRoutes(routes []*nbroute.Route) []*proto.RouteR
return out
}
func (e *componentEncoder) groupIDsToSeq(groupIDs []string) []uint32 {
func (e *componentEncoder) groupIDsToSeq(groupIDs []string) []int32 {
if len(groupIDs) == 0 {
return nil
}
out := make([]uint32, 0, len(groupIDs))
out := make([]int32, 0, len(groupIDs))
for _, gid := range groupIDs {
if seq, ok := e.groupSeq(gid); ok {
out = append(out, seq)
@@ -587,11 +585,11 @@ func (e *componentEncoder) encodeNetworkResources(resources []*resourceTypes.Net
return out
}
func (e *componentEncoder) encodeRoutersMap(routersMap map[string]map[string]*routerTypes.NetworkRouter) map[uint32]*proto.NetworkRouterList {
func (e *componentEncoder) encodeRoutersMap(routersMap map[string]map[string]*routerTypes.NetworkRouter) map[int32]*proto.NetworkRouterList {
if len(routersMap) == 0 {
return nil
}
out := make(map[uint32]*proto.NetworkRouterList, len(routersMap))
out := make(map[int32]*proto.NetworkRouterList, len(routersMap))
for networkXID, routers := range routersMap {
if len(routers) == 0 {
continue
@@ -623,42 +621,42 @@ func (e *componentEncoder) encodeRoutersMap(routersMap map[string]map[string]*ro
return out
}
func (e *componentEncoder) encodeResourcePoliciesMap(rpm map[string][]*types.Policy, policyToIdxs map[*types.Policy][]uint32) map[uint32]*proto.PolicyIndexes {
func (e *componentEncoder) encodeResourcePoliciesMap(rpm map[string][]*types.Policy) map[int32]*proto.PolicyIds {
if len(rpm) == 0 {
return nil
}
// resourceXIDToSeq is local to one encode — built from components.NetworkResources
// (small slice). Network resources without seq id are dropped, matching how
// other components-without-seq are silently filtered.
resourceXIDToSeq := make(map[string]uint32, len(e.components.NetworkResources))
resourceXIDToSeq := make(map[string]int32, len(e.components.NetworkResources))
for _, r := range e.components.NetworkResources {
if r != nil && r.AccountSeqID != 0 {
resourceXIDToSeq[r.ID] = r.AccountSeqID
}
}
out := make(map[uint32]*proto.PolicyIndexes, len(rpm))
out := make(map[int32]*proto.PolicyIds, len(rpm))
for resourceXID, policies := range rpm {
seq, ok := resourceXIDToSeq[resourceXID]
if !ok {
continue
}
idxs := make([]uint32, 0, len(policies)*2)
ids := make([]int32, 0, len(policies))
for _, pol := range policies {
idxs = append(idxs, policyToIdxs[pol]...)
ids = append(ids, pol.AccountSeqID)
}
if len(idxs) == 0 {
if len(ids) == 0 {
continue
}
out[seq] = &proto.PolicyIndexes{Indexes: idxs}
out[seq] = &proto.PolicyIds{Ids: ids}
}
return out
}
func (e *componentEncoder) encodeGroupIDToUserIDs(m map[string][]string) map[uint32]*proto.UserIDList {
func (e *componentEncoder) encodeGroupIDToUserIDs(m map[string][]string) map[int32]*proto.UserIDList {
if len(m) == 0 {
return nil
}
out := make(map[uint32]*proto.UserIDList, len(m))
out := make(map[int32]*proto.UserIDList, len(m))
for groupID, userIDs := range m {
seq, ok := e.groupSeq(groupID)
if !ok || len(userIDs) == 0 {
@@ -680,11 +678,11 @@ func stringSetToSlice(s map[string]struct{}) []string {
return out
}
func (e *componentEncoder) encodePostureFailedPeers(m map[string]map[string]struct{}) map[uint32]*proto.PeerIndexSet {
func (e *componentEncoder) encodePostureFailedPeers(m map[string]map[string]struct{}) map[int32]*proto.PeerIndexSet {
if len(m) == 0 {
return nil
}
out := make(map[uint32]*proto.PeerIndexSet, len(m))
out := make(map[int32]*proto.PeerIndexSet, len(m))
for checkXID, failedPeerIDs := range m {
seq, ok := e.components.PostureCheckXIDToSeq[checkXID]
if !ok || seq == 0 {
@@ -736,12 +734,12 @@ func toAccountNetwork(n *types.Network) *proto.AccountNetwork {
return out
}
func toPeerCompact(p *nbpeer.Peer, agentVersionIdx uint32) *proto.PeerCompact {
func toPeerCompact(p *nbpeer.Peer) *proto.PeerCompact {
pc := &proto.PeerCompact{
WgPubKey: decodeWgKey(p.Key),
SshPubKey: []byte(p.SSHKey),
DnsLabel: p.DNSLabel,
AgentVersionIdx: agentVersionIdx,
AgentVersion: p.Meta.WtVersion,
AddedWithSsoLogin: p.UserID != "",
LoginExpirationEnabled: p.LoginExpirationEnabled,
SshEnabled: p.SSHEnabled,

View File

@@ -29,20 +29,20 @@ func (p NetworkResourceType) String() string {
}
type NetworkResource struct {
ID string `gorm:"primaryKey"`
NetworkID string `gorm:"index"`
AccountID string `gorm:"index"`
ID string `gorm:"primaryKey"`
NetworkID string `gorm:"index"`
AccountID string `gorm:"index"`
// AccountSeqID is a per-account monotonically increasing identifier used as the
// compact wire id when sending NetworkMap components to capable peers.
AccountSeqID uint32 `json:"-" gorm:"index:idx_network_resources_account_seq_id;not null;default:0"`
Name string
Description string
Type NetworkResourceType
Address string `gorm:"-"`
GroupIDs []string `gorm:"-"`
Domain string
Prefix netip.Prefix `gorm:"serializer:json"`
Enabled bool
AccountSeqID int32 `json:"-" gorm:"not null;default:0"`
Name string
Description string
Type NetworkResourceType
Address string `gorm:"-"`
GroupIDs []string `gorm:"-"`
Domain string
Prefix netip.Prefix `gorm:"serializer:json"`
Enabled bool
}
func NewNetworkResource(accountID, networkID, name, description, address string, groupIDs []string, enabled bool) (*NetworkResource, error) {

View File

@@ -10,17 +10,17 @@ import (
)
type NetworkRouter struct {
ID string `gorm:"primaryKey"`
NetworkID string `gorm:"index"`
AccountID string `gorm:"index"`
ID string `gorm:"primaryKey"`
NetworkID string `gorm:"index"`
AccountID string `gorm:"index"`
// AccountSeqID is a per-account monotonically increasing identifier used as the
// compact wire id when sending NetworkMap components to capable peers.
AccountSeqID uint32 `json:"-" gorm:"index:idx_network_routers_account_seq_id;not null;default:0"`
Peer string
PeerGroups []string `gorm:"serializer:json"`
Masquerade bool
Metric int
Enabled bool
AccountSeqID int32 `json:"-" gorm:"not null;default:0"`
Peer string
PeerGroups []string `gorm:"serializer:json"`
Masquerade bool
Metric int
Enabled bool
}
func NewNetworkRouter(accountID string, networkID string, peer string, peerGroups []string, masquerade bool, metric int, enabled bool) (*NetworkRouter, error) {

View File

@@ -12,7 +12,7 @@ type Network struct {
// AccountSeqID is a per-account monotonically increasing identifier used as the
// compact wire id when sending NetworkMap components to capable peers.
AccountSeqID uint32 `json:"-" gorm:"index:idx_networks_account_seq_id;not null;default:0"`
AccountSeqID int32 `json:"-" gorm:"not null;default:0"`
Name string
Description string

View File

@@ -51,7 +51,7 @@ type Checks struct {
// AccountSeqID is a per-account monotonically increasing identifier used as the
// compact wire id when sending NetworkMap components to capable peers.
AccountSeqID uint32 `json:"-" gorm:"index:idx_posture_checks_account_seq_id;not null;default:0"`
AccountSeqID int32 `json:"-" gorm:"not null;default:0"`
// Checks is a set of objects that perform the actual checks
Checks ChecksDefinition `gorm:"serializer:json"`

View File

@@ -3637,11 +3637,11 @@ func (s *SqlStore) withTx(tx *gorm.DB) Store {
// AllocateAccountSeqID returns the next per-account integer id for the given
// component kind. Must be called inside ExecuteInTransaction so the increment
// is serialized with the component insert.
func (s *SqlStore) AllocateAccountSeqID(ctx context.Context, accountID string, entity types.AccountSeqEntity) (uint32, error) {
func (s *SqlStore) AllocateAccountSeqID(ctx context.Context, accountID string, entity types.AccountSeqEntity) (int32, error) {
return allocateAccountSeqID(ctx, s.db, s.storeEngine, accountID, entity)
}
func allocateAccountSeqID(_ context.Context, db *gorm.DB, engine types.Engine, accountID string, entity types.AccountSeqEntity) (uint32, error) {
func allocateAccountSeqID(_ context.Context, db *gorm.DB, engine types.Engine, accountID string, entity types.AccountSeqEntity) (int32, error) {
switch engine {
case types.PostgresStoreEngine, types.SqliteStoreEngine:
return allocateAccountSeqIDReturning(db, accountID, entity)
@@ -3657,7 +3657,7 @@ func allocateAccountSeqID(_ context.Context, db *gorm.DB, engine types.Engine, a
// SELECT FOR UPDATE. Two concurrent allocations for the same (account, entity)
// produce two distinct ids: one wins the INSERT, the other wins the UPDATE
// branch and returns next_id+1.
func allocateAccountSeqIDReturning(db *gorm.DB, accountID string, entity types.AccountSeqEntity) (uint32, error) {
func allocateAccountSeqIDReturning(db *gorm.DB, accountID string, entity types.AccountSeqEntity) (int32, error) {
const sqlStr = `
INSERT INTO account_seq_counters (account_id, entity, next_id)
VALUES (?, ?, 2)
@@ -3665,7 +3665,7 @@ func allocateAccountSeqIDReturning(db *gorm.DB, accountID string, entity types.A
SET next_id = account_seq_counters.next_id + 1
RETURNING (next_id - 1)
`
var allocated uint32
var allocated int32
if err := db.Raw(sqlStr, accountID, string(entity)).Scan(&allocated).Error; err != nil {
return 0, fmt.Errorf("upsert account seq counter: %w", err)
}
@@ -3682,7 +3682,7 @@ func allocateAccountSeqIDReturning(db *gorm.DB, accountID string, entity types.A
// no-conflict path also surfaces the new next_id, keeping the read-back uniform.
// LAST_INSERT_ID is per-connection; GORM transactions pin a single connection,
// so the follow-up SELECT sees the same value.
func allocateAccountSeqIDMysql(db *gorm.DB, accountID string, entity types.AccountSeqEntity) (uint32, error) {
func allocateAccountSeqIDMysql(db *gorm.DB, accountID string, entity types.AccountSeqEntity) (int32, error) {
const upsertSQL = `
INSERT INTO account_seq_counters (account_id, entity, next_id)
VALUES (?, ?, LAST_INSERT_ID(2))
@@ -3698,7 +3698,7 @@ func allocateAccountSeqIDMysql(db *gorm.DB, accountID string, entity types.Accou
if newNext == 0 {
return 0, fmt.Errorf("LAST_INSERT_ID returned 0; account_seq_counters misconfigured")
}
return uint32(newNext - 1), nil
return int32(newNext - 1), nil
}
// assignAccountSeqIDs allocates a per-account integer id for any component on
@@ -3709,8 +3709,8 @@ func allocateAccountSeqIDMysql(db *gorm.DB, accountID string, entity types.Accou
// per-entity counter is bumped so subsequent AllocateAccountSeqID calls don't
// hand out a colliding id.
func (s *SqlStore) assignAccountSeqIDs(ctx context.Context, tx *gorm.DB, account *types.Account) error {
maxByEntity := make(map[types.AccountSeqEntity]uint32, 8)
bump := func(entity types.AccountSeqEntity, seq uint32) {
maxByEntity := make(map[types.AccountSeqEntity]int32, 8)
bump := func(entity types.AccountSeqEntity, seq int32) {
if seq > maxByEntity[entity] {
maxByEntity[entity] = seq
}
@@ -3856,7 +3856,7 @@ func (s *SqlStore) assignAccountSeqIDs(ctx context.Context, tx *gorm.DB, account
// AccountSeqIDs (e.g. test bulk-load from sqlite to postgres, or migrations
// running before component data lands) so that the next AllocateAccountSeqID
// call returns a fresh id beyond what was just written.
func ensureAccountSeqCounter(db *gorm.DB, engine types.Engine, accountID string, entity types.AccountSeqEntity, target uint32) error {
func ensureAccountSeqCounter(db *gorm.DB, engine types.Engine, accountID string, entity types.AccountSeqEntity, target int32) error {
switch engine {
case types.PostgresStoreEngine, types.SqliteStoreEngine:
const sqlStr = `

View File

@@ -226,7 +226,7 @@ type Store interface {
// AllocateAccountSeqID returns the next per-account integer id for the given
// component kind. Must run inside a transaction so the increment is serialized
// with the component insert.
AllocateAccountSeqID(ctx context.Context, accountID string, entity types.AccountSeqEntity) (uint32, error)
AllocateAccountSeqID(ctx context.Context, accountID string, entity types.AccountSeqEntity) (int32, error)
GetAccountNetworks(ctx context.Context, lockStrength LockingStrength, accountID string) ([]*networkTypes.Network, error)
GetNetworkByID(ctx context.Context, lockStrength LockingStrength, accountID, networkID string) (*networkTypes.Network, error)

View File

@@ -134,8 +134,8 @@ func (a *Account) GetPeerNetworkMapComponents(
NetworkResources: make([]*resourceTypes.NetworkResource, 0),
PostureFailedPeers: make(map[string]map[string]struct{}, len(a.PostureChecks)),
RouterPeers: make(map[string]*nbpeer.Peer),
NetworkXIDToSeq: make(map[string]uint32, len(a.Networks)),
PostureCheckXIDToSeq: make(map[string]uint32, len(a.PostureChecks)),
NetworkXIDToSeq: make(map[string]int32, len(a.Networks)),
PostureCheckXIDToSeq: make(map[string]int32, len(a.PostureChecks)),
}
for _, n := range a.Networks {
if n != nil && n.HasSeqID() {

View File

@@ -97,7 +97,7 @@ type Route struct {
AccountID string `gorm:"index"`
// AccountSeqID is a per-account monotonically increasing identifier used as the
// compact wire id when sending NetworkMap components to capable peers.
AccountSeqID uint32 `json:"-" gorm:"index:idx_routes_account_seq_id;not null;default:0"`
AccountSeqID int32 `json:"-" gorm:"not null;default:0"`
// Network and Domains are mutually exclusive
Network netip.Prefix `gorm:"serializer:json"`
Domains domain.List `gorm:"serializer:json"`

File diff suppressed because it is too large Load Diff

View File

@@ -864,16 +864,16 @@ message NetworkMapComponentsFull {
// entry because capability=3 has never been released — every cap=3
// producer and consumer carries the same regenerated descriptor. Do NOT
// reuse this pattern for any further wire change once cap=3 ships.
map<uint32, NetworkRouterList> routers_map = 18;
map<int32, NetworkRouterList> routers_map = 18;
// For each NetworkResource account_seq_id, the indexes into policies[]
// that apply to it.
//
// INCOMPATIBLE WIRE CHANGE: see routers_map note above.
map<uint32, PolicyIndexes> resource_policies_map = 19;
map<int32, PolicyIds> resource_policies_map = 19;
// Group-id (account_seq_id) → user ids authorized for SSH on members.
map<uint32, UserIDList> group_id_to_user_ids = 20;
map<int32, UserIDList> group_id_to_user_ids = 20;
// Account-level allowed user ids (used by Calculate() when assembling SSH
// authorized users for the receiving peer).
@@ -883,7 +883,7 @@ message NetworkMapComponentsFull {
// the check. Server-side evaluation result; clients do not re-evaluate.
//
// INCOMPATIBLE WIRE CHANGE: see routers_map note above.
map<uint32, PeerIndexSet> posture_failed_peers = 22;
map<int32, PeerIndexSet> posture_failed_peers = 22;
// Account-level DNS forwarder port (mirrors the legacy
// proto.DNSConfig.ForwarderPort). Computed by the controller from peer
@@ -978,8 +978,7 @@ message PeerCompact {
// dns_label + "." + NetworkMapComponentsFull.dns_domain.
string dns_label = 5;
// Index into NetworkMapComponentsFull.agent_versions.
uint32 agent_version_idx = 6;
string agent_version = 6;
// True iff the peer was added via SSO login (i.e., types.Peer.UserID is
// non-empty). Combined with login_expiration_enabled and
@@ -1003,25 +1002,23 @@ message PeerCompact {
// peer when this bit is set, even without an explicit NetbirdSSH rule.
bool ssh_enabled = 10;
reserved 11; // was: id (string xid)
// Mirror of types.Peer.SupportsIPv6() — !Meta.Flags.DisableIPv6 &&
// HasCapability(PeerCapabilityIPv6Overlay). Used by the local peer's
// Calculate() when deciding whether to emit IPv6 firewall rules
// (appendIPv6FirewallRule) against this peer's IPv6 address.
bool supports_ipv6 = 12;
bool supports_ipv6 = 11;
// Mirror of types.Peer.SupportsSourcePrefixes() —
// HasCapability(PeerCapabilitySourcePrefixes). Determines whether the
// local peer's Calculate() emits SourcePrefixes alongside legacy PeerIP
// fields in proto.FirewallRule.
bool supports_source_prefixes = 13;
bool supports_source_prefixes = 12;
// Mirror of types.Peer.Meta.Flags.ServerSSHAllowed. Read by Calculate()
// when expanding TCP port-22 firewall rules — the native SSH companion
// (port 22022) is only added when this flag is set and the peer agent
// version supports it.
bool server_ssh_allowed = 14;
bool server_ssh_allowed = 13;
}
// PolicyCompact is the compact form of a policy rule. Group references use
@@ -1033,7 +1030,7 @@ message PolicyCompact {
// Per-account integer id (matches policies.account_seq_id). Used as a
// stable reference for ResourcePoliciesMap.indexes and future delta
// updates.
uint32 id = 1;
int32 id = 1;
RuleAction action = 2;
RuleProtocol protocol = 3;
@@ -1046,10 +1043,8 @@ message PolicyCompact {
repeated PortInfo.Range port_ranges = 6;
// Group ids (account_seq_id) of source / destination groups.
repeated uint32 source_group_ids = 7;
repeated uint32 destination_group_ids = 8;
reserved 9; // was: xid (string)
repeated int32 source_group_ids = 7;
repeated int32 destination_group_ids = 8;
// SSH authorization fields. PolicyRule.AuthorizedGroups maps the rule's
// applicable group ids (account_seq_id) to a list of local-user names —
@@ -1059,8 +1054,8 @@ message PolicyCompact {
//
// Both fields are only consumed by Calculate() when the rule's protocol
// is NetbirdSSH (or the legacy implicit-SSH heuristic).
map<uint32, UserNameList> authorized_groups = 10;
string authorized_user = 11;
map<int32, UserNameList> authorized_groups = 9;
string authorized_user = 10;
// Resource-typed rule sources/destinations. When a rule targets a specific
// peer (rather than groups), Calculate() reads SourceResource /
@@ -1069,16 +1064,14 @@ message PolicyCompact {
// NetworkMapComponentsFull.peers; type is the raw ResourceType string
// ("peer", "host", "subnet", "domain"). Only "peer" is meaningful for
// Calculate's resource-typed rule path today.
ResourceCompact source_resource = 12;
ResourceCompact destination_resource = 13;
ResourceCompact source_resource = 11;
ResourceCompact destination_resource = 12;
// Posture-check seq ids gating this policy's source peers. Calculate()
// reads them when filtering rule peers (peers that fail any listed check
// are dropped from sourcePeers). Match keys in
// NetworkMapComponentsFull.posture_failed_peers.
repeated uint32 source_posture_check_seq_ids = 15;
reserved 14; // was: source_posture_check_ids (repeated string xid)
repeated int32 source_posture_check_seq_ids = 13;
}
// ResourceCompact mirrors types.Resource. Used by PolicyCompact to carry
@@ -1104,7 +1097,7 @@ message UserNameList {
message GroupCompact {
// Per-account integer id (matches groups.account_seq_id). Used by
// PolicyCompact.source_group_ids / destination_group_ids.
uint32 id = 1;
int32 id = 1;
// Group name; only sent when non-empty (clients use it for diagnostics).
string name = 2;
@@ -1116,7 +1109,7 @@ message GroupCompact {
// DNSSettingsCompact mirrors types.DNSSettings.
message DNSSettingsCompact {
// Group ids (account_seq_id) whose DNS management is disabled.
repeated uint32 disabled_management_group_ids = 1;
repeated int32 disabled_management_group_ids = 1;
}
// RouteRaw mirrors *route.Route (the domain type), trimmed to fields that
@@ -1125,7 +1118,7 @@ message DNSSettingsCompact {
// NetworkMapComponentsFull.peers.
message RouteRaw {
// Per-account integer id (matches routes.account_seq_id).
uint32 id = 1;
int32 id = 1;
string net_id = 2;
string description = 3;
@@ -1146,30 +1139,28 @@ message RouteRaw {
// path will substitute the WG key downstream.
bool peer_index_set = 7;
uint32 peer_index = 8;
repeated uint32 peer_group_ids = 9;
repeated int32 peer_group_ids = 9;
int32 network_type = 10;
bool masquerade = 11;
int32 metric = 12;
bool enabled = 13;
repeated uint32 group_ids = 14;
repeated uint32 access_control_group_ids = 15;
repeated int32 group_ids = 14;
repeated int32 access_control_group_ids = 15;
bool skip_auto_apply = 16;
reserved 17; // was: xid (string)
}
// NameServerGroupRaw mirrors *nbdns.NameServerGroup. Distinct from the
// legacy NameServerGroup (which is the wire-trimmed shape consumed by
// proto.DNSConfig and lacks the Name/Description/Groups/Enabled fields).
message NameServerGroupRaw {
uint32 id = 1; // nameserver_groups.account_seq_id
int32 id = 1; // nameserver_groups.account_seq_id
string name = 2;
string description = 3;
// Reuses the legacy NameServer wire shape (IP as string).
repeated NameServer nameservers = 4;
// Group ids (account_seq_id) the NSG distributes nameservers to.
repeated uint32 group_ids = 5;
repeated int32 group_ids = 5;
bool primary = 6;
repeated string domains = 7;
bool enabled = 8;
@@ -1184,8 +1175,8 @@ message NameServerGroupRaw {
// carries the same regenerated descriptor. Do NOT reuse this pattern once
// cap=3 ships.
message NetworkResourceRaw {
uint32 id = 1; // network_resources.account_seq_id
uint32 network_seq = 2; // networks.account_seq_id (replaces xid)
int32 id = 1; // network_resources.account_seq_id
int32 network_seq = 2; // networks.account_seq_id (replaces xid)
string name = 3;
string description = 4;
// Resource type: "host" / "subnet" / "domain".
@@ -1194,7 +1185,6 @@ message NetworkResourceRaw {
string domain_value = 7; // resource.Domain
string prefix_cidr = 8;
bool enabled = 9;
reserved 10; // was: xid (string)
}
// NetworkRouterList carries the routers backing one network.
@@ -1206,18 +1196,17 @@ message NetworkRouterList {
// NetworkRouterEntry mirrors a single *routerTypes.NetworkRouter; the routing
// peer is referenced by index into NetworkMapComponentsFull.peers.
message NetworkRouterEntry {
uint32 id = 1; // network_routers.account_seq_id
int32 id = 1; // network_routers.account_seq_id
uint32 peer_index = 2;
bool peer_index_set = 3;
repeated uint32 peer_group_ids = 4;
repeated int32 peer_group_ids = 4;
bool masquerade = 5;
int32 metric = 6;
bool enabled = 7;
}
// PolicyIndexes is a list of indexes into NetworkMapComponentsFull.policies.
message PolicyIndexes {
repeated uint32 indexes = 1;
message PolicyIds {
repeated int32 ids = 1;
}
// UserIDList is a list of user ids — used as the value type in

View File

@@ -21,7 +21,7 @@ type Group struct {
// AccountSeqID is a per-account monotonically increasing identifier used as the
// compact wire id when sending NetworkMap components to capable peers.
AccountSeqID uint32 `json:"-" gorm:"index:idx_groups_account_seq_id;not null;default:0"`
AccountSeqID int32 `json:"-" gorm:"not null;default:0"`
// Name visible in the UI
Name string

View File

@@ -47,12 +47,12 @@ type NetworkMapComponents struct {
// account-side component builder; consumed by the envelope encoder to
// translate RoutersMap keys and NetworkResource.NetworkID references
// to compact uint32 ids. Legacy Calculate() doesn't consult it.
NetworkXIDToSeq map[string]uint32
NetworkXIDToSeq map[string]int32
// PostureCheckXIDToSeq maps posture.Checks.ID (xid) → AccountSeqID.
// Same role as NetworkXIDToSeq, used for PostureFailedPeers keys and
// policy SourcePostureChecks references.
PostureCheckXIDToSeq map[string]uint32
PostureCheckXIDToSeq map[string]int32
}
type AccountSettingsInfo struct {

View File

@@ -61,7 +61,7 @@ type Policy struct {
// AccountSeqID is a per-account monotonically increasing identifier used as the
// compact wire id when sending NetworkMap components to capable peers.
AccountSeqID uint32 `json:"-" gorm:"index:idx_policies_account_seq_id;not null;default:0"`
AccountSeqID int32 `json:"-" gorm:"not null;default:0"`
// Name of the Policy
Name string