feat: add invite code validity controls

- Add invite code starts/expires fields across contracts, API, Spacetime bindings, and admin UI
- Enforce pending/expired invite code redemption behavior and expose admin status
- Add admin write-operation confirmation guard and documentation
- Add invite code contract/runtime tests
This commit is contained in:
2026-05-04 12:29:33 +08:00
parent 1142e90a35
commit 9f3e34e81a
27 changed files with 1465 additions and 97 deletions

View File

@@ -281,6 +281,8 @@ impl From<module_runtime::RuntimeProfileInviteCodeAdminUpsertInput>
admin_user_id: input.admin_user_id,
invite_code: input.invite_code,
metadata_json: input.metadata_json,
starts_at_micros: input.starts_at_micros,
expires_at_micros: input.expires_at_micros,
updated_at_micros: input.updated_at_micros,
}
}
@@ -1997,6 +1999,8 @@ pub(crate) fn map_runtime_profile_invite_code_snapshot(
user_id: snapshot.user_id,
invite_code: snapshot.invite_code,
metadata_json: snapshot.metadata_json,
starts_at_micros: snapshot.starts_at_micros,
expires_at_micros: snapshot.expires_at_micros,
created_at_micros: snapshot.created_at_micros,
updated_at_micros: snapshot.updated_at_micros,
}

View File

@@ -12,6 +12,8 @@ pub struct ProfileInviteCode {
pub metadata_json: String,
pub created_at: __sdk::Timestamp,
pub updated_at: __sdk::Timestamp,
pub starts_at: Option<__sdk::Timestamp>,
pub expires_at: Option<__sdk::Timestamp>,
}
impl __sdk::InModule for ProfileInviteCode {
@@ -27,6 +29,8 @@ pub struct ProfileInviteCodeCols {
pub metadata_json: __sdk::__query_builder::Col<ProfileInviteCode, String>,
pub created_at: __sdk::__query_builder::Col<ProfileInviteCode, __sdk::Timestamp>,
pub updated_at: __sdk::__query_builder::Col<ProfileInviteCode, __sdk::Timestamp>,
pub starts_at: __sdk::__query_builder::Col<ProfileInviteCode, Option<__sdk::Timestamp>>,
pub expires_at: __sdk::__query_builder::Col<ProfileInviteCode, Option<__sdk::Timestamp>>,
}
impl __sdk::__query_builder::HasCols for ProfileInviteCode {
@@ -38,6 +42,8 @@ impl __sdk::__query_builder::HasCols for ProfileInviteCode {
metadata_json: __sdk::__query_builder::Col::new(table_name, "metadata_json"),
created_at: __sdk::__query_builder::Col::new(table_name, "created_at"),
updated_at: __sdk::__query_builder::Col::new(table_name, "updated_at"),
starts_at: __sdk::__query_builder::Col::new(table_name, "starts_at"),
expires_at: __sdk::__query_builder::Col::new(table_name, "expires_at"),
}
}
}

View File

@@ -10,6 +10,8 @@ pub struct RuntimeProfileInviteCodeAdminUpsertInput {
pub admin_user_id: String,
pub invite_code: String,
pub metadata_json: String,
pub starts_at_micros: Option<i64>,
pub expires_at_micros: Option<i64>,
pub updated_at_micros: i64,
}

View File

@@ -10,6 +10,8 @@ pub struct RuntimeProfileInviteCodeSnapshot {
pub user_id: String,
pub invite_code: String,
pub metadata_json: String,
pub starts_at_micros: Option<i64>,
pub expires_at_micros: Option<i64>,
pub created_at_micros: i64,
pub updated_at_micros: i64,
}

View File

@@ -533,12 +533,16 @@ impl SpacetimeClient {
admin_user_id: String,
invite_code: String,
metadata_json: String,
starts_at_micros: Option<i64>,
expires_at_micros: Option<i64>,
updated_at_micros: i64,
) -> Result<RuntimeProfileInviteCodeRecord, SpacetimeClientError> {
let procedure_input = build_runtime_profile_invite_code_admin_upsert_input(
admin_user_id,
invite_code,
metadata_json,
starts_at_micros,
expires_at_micros,
updated_at_micros,
)
.map_err(|error| SpacetimeClientError::Runtime(error.to_string()))?