Public APIs must make their guarantees and caller responsibilities explicit—especially around encapsulation, lifecycle/ownership, and callback semantics.

Guidelines:

Example pattern (copy callback semantics):

/* Copy callback: update *meta and return whether metadata is kept. */
static int KeyMetaCopyCallback(RedisModuleKeyOptCtx *ctx, uint64_t *meta) {
    REDISMODULE_NOT_USED(ctx);
    char *str = (char *)*meta;
    if (str) {
        char *new_str = strdup(str);
        *meta = (uint64_t)new_str; /* API contract: update out-param */
    }
    return 1; /* keep metadata */
}

If you introduce sentinel values or out-parameter replacement behavior, treat it as an API contract: make the sentinel meaning explicit, define when callbacks are skipped, and provide short examples in the docs or tests so module authors don’t guess.