feat: customer add command#40
Conversation
| // DID of the user account e.g. `did:mailto:agent` | ||
| Customer did.DID `cborgen:"customer" dagjsongen:"customer"` |
There was a problem hiding this comment.
We must be careful here.
At the moment, FilOne Console assumes user=organization. We know we will need to support multi-user organisations in the future, FilOne Console's database model is a sort of half-way there.
In the context of libforge, we should make it clear whether Customer is "FilOne organization account" or "FilOne user account".
Since buckets are owned by organizations, not users, I am arguing that we should treat Customer as "organization account" here.
| // DID of the user account e.g. `did:mailto:agent` | |
| Customer did.DID `cborgen:"customer" dagjsongen:"customer"` | |
| // DID of the FilOne organization account e.g. `did:mailto:agent` | |
| Customer did.DID `cborgen:"customer" dagjsongen:"customer"` |
But since I see Account below, perhaps I misunderstood the proposed data model. Is there any prior documentation describing how Forge components will use these customer records?
There was a problem hiding this comment.
I think that's fine. In Forge a customer is some entity that pays for storage. This tallies with an organization in Fil One.
There was a problem hiding this comment.
(More context:) Contrasted with an account, which is some entity that represents (generally) a human user. Generally a customer is an account, but not necessarily the account that generally works with the space, or even necessarily has any capabilities on the space.
There was a problem hiding this comment.
Makes sense, thank you for the explanation.
I still think we should change the comment to avoid confusion. How about the following?
| // DID of the user account e.g. `did:mailto:agent` | |
| Customer did.DID `cborgen:"customer" dagjsongen:"customer"` | |
| // DID of the customer account e.g. `did:mailto:agent` | |
| Customer did.DID `cborgen:"customer" dagjsongen:"customer"` |
| // Opaque identifier representing an account in the payment system | ||
| // e.g. Stripe customer ID (stripe:cus_9s6XKzkNRiz8i3) | ||
| Account *string `cborgen:"account,omitempty" dagjsongen:"account,omitempty"` |
There was a problem hiding this comment.
Is it a good idea to use Stripe customer ID here? FilOne is using orgId (a UUID generated by FilOne backend) as the unique identifier of the organisation account.
Conceptually, I believe each FilOne organization account has exactly one linked Stripe customer record.
In the current FilOne backend data model, Stripe customer ID is stored in BillingTable with pk: CUSTOMER#{userId}, sk: SUBSCRIPTION, I guess that's something we will need to change.
@pyropy is my understanding correct?
There was a problem hiding this comment.
Since Fil One are the billing provider for the customer then I think it's appropriate to put the Fil One ID here (with an f1: prefix or something). This will come from Hilt, so it'll be what Hilt calls the tenant ID, which I assume is the same thing as the Fil One org ID.
There was a problem hiding this comment.
Since Fil One are the billing provider for the customer then I think it's appropriate to put the Fil One ID here (with an
f1:prefix or something). This will come from Hilt, so it'll be what Hilt calls the tenant ID, which I assume is the same thing as the Fil One org ID.
I like that!
There was a problem hiding this comment.
I suggest calling this field BillingAccountId or PaymentAccountId to make it clear this is not the same thing as the "Forge account" we are discussing in https://github.com/fil-forge/libforge/pull/40/changes#r3492457770
There was a problem hiding this comment.
On second thought, if this is going to contain FilOne OrgId, then I think ExternalAccountId captures the intent best.
|
|
||
| type AddArguments struct { | ||
| // DID of the user account e.g. `did:mailto:agent` | ||
| Customer did.DID `cborgen:"customer" dagjsongen:"customer"` |
There was a problem hiding this comment.
What is the difference between Consumer (used by /provider/add command) and Customer?
libforge/commands/provider/types.go
Line 7 in eb26d87
There was a problem hiding this comment.
A consumer is the space (bucket).
The (simplified) ER diagram looks like this:
erDiagram
CUSTOMER ||--o{ SUBSCRIPTION : has
SUBSCRIPTION ||--o{ CONSUMER : subscribes
CUSTOMER {
DID customer PK
string account
}
SUBSCRIPTION {
CID subscription PK
DID customer FK
}
CONSUMER {
DID consumer PK
CID subscription FK
}
In the CUSTOMER table, the account field is the ID in the external billing system for the customer. The ID of a customer has traditionally been a did:mailto:, but will be a did:plc: for Fil One orgs.
The SUBSCRIPTION table maps a customer paying for 1 or many spaces.
The CONSUMER table is the space(s) that will be billed for as part of the subscription.
The structure is designed so that moving spaces or groups of spaces between customers is easy.
There was a problem hiding this comment.
Thank you for the explanation and the diagram; it's super helpful!
I feel we are creating confusing vocabulary here.
In my understanding (which may be wrong, I am not a native English speaker): The terms "consumer" and "customer" are often used interchangeably, e.g. if I buy an iPhone with an iCloud subscription, I am both "customer" of Apple and also "consumer" of Apple services.
Claude's answer:
A customer buys something; a consumer uses or consumes it. They're often the same person, but not always.
The core distinction is the role in the transaction. A customer is whoever pays for a product or service. A consumer is whoever actually uses it. When a parent buys baby food, the parent is the customer and the baby is the consumer. When you buy dog food, you're the customer; your dog is the consumer.
Which seems to confirm my view - as a FilOne user, I am both the customer (paying for the service) and the consumer (using the storage service).
I can see how "consumer" may have been a good name before "customer" entered the picture, but I cannot help but find the new domain model very confusing.
Can we find a different name for the Consumer entity?
A few suggestions from Claude:
Space— This is what Alan literally calls it in prose ("A consumer is the space (bucket)"). It matches the domain vocabulary already used elsewhere ("spaces to be provisioned"). Clearest and most honest.BillableSpaceorSubscribedSpace— If you want to keep the emphasis that this is specifically the space as attached to a subscription for billing, rather than the space in general.SubscriptionItem/SubscriptionEntry— If you want to foreground the relationship (what a subscription contains) rather than the resource itself. This mirrors Stripe's own subscription_item naming, which fits given the Stripe alignment discussed elsewhere in the PR. Downside: less concrete about what the item is.
I like Space most, with SubscribedSpace as an option if we want to emphasise the relation to subscriptions.
There was a problem hiding this comment.
I agree it is confusing. It also looks very similar to customer so easy to read incorrectly at a glance. I will create a follow up ticket to rename consumer since this is out of scope for this PR.
FWIW I think the original idea here was explicitly not to call it space to allow things that we do not consider to be "spaces" to be billed for.
Adds the S3 commands as specified in fil-one/RFC#8 A few of the types have some hand-rolled CBOR/JSON encoders/decoders since for some reason `cbor-gen` (and hence `dag-json-gen`) do not support slices as map values.
An invocation that Hilt can make to insert a customer directly into the upload service DB.
Customers added by Hilt are "tenants" that are authenticated, authorized and billed by fil.one. However they need to be registered in the upload service to allow spaces to be provisioned and used.