Hi Willy,
Yes, this is possible without modifying Discourse core files.
You can use Discourse groups to manage membership access and a small custom plugin to handle expiration dates.
For example, the expiration date could be stored like this:
user.upsert_custom_fields(
membership_expires_at: 6.months.from_now.iso8601
)
A scheduled job could then check expired memberships and remove users from the members-only group:
Group.find_by(name: "members")&.remove(user)
When a user renews, simply update their expiration date and add them back to the group.
These are basic code examples, not a complete plugin, but they illustrate the approach.
For paid memberships, you can also check the official Discourse Subscriptions plugin.
Hope this helps!